EKS Cluster Creation Quiz - Part 2
This quiz tests your understanding of advanced concepts, security settings, and networking configurations related to Amazon EKS cluster creation. It covers topics such as cluster security, network policies, and service accounts.
Basic Concept Questions
- What is the main purpose of IRSA (IAM Roles for Service Accounts) in an Amazon EKS cluster?
- A) Granting IAM permissions to cluster administrators
- B) Assigning IAM roles to worker nodes
- C) Granting AWS service access permissions to Kubernetes service accounts
- D) Granting IAM permissions to the EKS control plane
Show Answer
Answer: C) Granting AWS service access permissions to Kubernetes service accounts
Explanation: The main purpose of IRSA (IAM Roles for Service Accounts) is to grant AWS service access permissions to Kubernetes service accounts. This feature allows you to provide fine-grained permissions at the pod level, and instead of sharing node-level IAM roles, you can grant only the minimum required permissions to each application.
How IRSA Works:
OpenID Connect (OIDC) Provider Setup:
- The EKS cluster is configured as an OIDC provider.
- This enables Kubernetes service account tokens to become a trusted authentication mechanism in AWS IAM.
bash# Associate OIDC provider eksctl utils associate-iam-oidc-provider --cluster my-cluster --approveCreate IAM Role and Configure Trust Policy:
- Create an IAM role that the Kubernetes service account can assume.
- The trust policy restricts only specific service accounts in specific namespaces to assume the role.
json{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.region.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.region.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-service-account" } } } ] }Create Service Account and Associate IAM Role:
- Add the IAM role ARN as an annotation to the service account.
yamlapiVersion: v1 kind: ServiceAccount metadata: name: my-service-account namespace: default annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-roleUse Service Account in Pod:
- Specify the service account in the pod manifest.
yamlapiVersion: v1 kind: Pod metadata: name: my-pod spec: serviceAccountName: my-service-account containers: - name: my-container image: my-image
Benefits of IRSA:
- Principle of Least Privilege:
- You can grant only the minimum required permissions to each application.
- Different permission settings per pod instead of sharing node-level IAM roles
- Enhanced Security:
- No need to store AWS credentials in code or environment variables.
- Reduced risk of credential leakage
- Permission Isolation:
- Different pods running on the same node can have different IAM permissions.
- Important in multi-tenant environments
- Simplified Credential Management:
- No need to directly manage AWS credentials.
- Credential rotation is handled automatically.
Example of IRSA Setup Using eksctl:
# Create service account and IAM role
eksctl create iamserviceaccount \
--name my-service-account \
--namespace default \
--cluster my-cluster \
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approve
# Verify created service account
kubectl get serviceaccount my-service-account -o yamlIssues with Other Options:
- Granting IAM permissions to cluster administrators: This is not the purpose of IRSA. Cluster administrator permissions are typically managed through the aws-auth ConfigMap.
- Assigning IAM roles to worker nodes: This is done through node IAM roles and is separate from IRSA. Node IAM roles are shared by all pods, which can violate the principle of least privilege.
- Granting IAM permissions to the EKS control plane: EKS control plane permissions are managed through the cluster IAM role and are unrelated to IRSA.
IRSA is an important feature that allows Kubernetes workloads to securely access AWS services and is the recommended approach when running applications on EKS clusters.
2. What is the main role of security groups in an Amazon EKS cluster? - A) Controlling network traffic between pods - B) Controlling traffic between the cluster API server and nodes - C) Applying Kubernetes RBAC policies - D) Managing user authentication
Show Answer
Answer: B) Controlling traffic between the cluster API server and nodes
Explanation: The main role of security groups in an Amazon EKS cluster is to control traffic between the cluster API server and nodes. Security groups are AWS virtual firewalls that control inbound and outbound traffic at the EC2 instance level. In EKS, there are cluster security groups and node security groups, which protect communication between cluster components.
Types of Security Groups in EKS Clusters:
- Cluster Security Group:
- Applied to the EKS control plane.
- Allows communication between worker nodes and the control plane.
- Automatically created by default when creating an EKS cluster.
- Key rules:
- Allow inbound traffic on port 443 from node security group
- Allow outbound traffic to node security group
- Node Security Group:
- Applied to worker nodes.
- Allows communication between nodes and between nodes and the control plane.
- Key rules:
- Allow all traffic between nodes
- Allow outbound traffic on port 443 to cluster security group
- Allow inbound traffic from cluster security group
- Allow port 10250 for kubelet
Security Group Configuration Examples:
Cluster Security Group Rules:
Inbound:
- Protocol: TCP
- Port Range: 443
- Source: Node Security Group
Outbound:
- Protocol: All Traffic
- Port Range: All Ports
- Destination: 0.0.0.0/0Node Security Group Rules:
Inbound:
- Protocol: All Traffic
- Source: Node Security Group itself (node-to-node communication)
- Protocol: TCP
- Port Range: 10250
- Source: Cluster Security Group (kubelet communication)
Outbound:
- Protocol: All Traffic
- Port Range: All Ports
- Destination: 0.0.0.0/0Customizing Security Groups:
You can specify custom security groups when creating an EKS cluster:
# Specifying custom security groups using AWS CLI
aws eks create-cluster \
--name my-cluster \
--role-arn arn:aws:iam::123456789012:role/EksClusterRole \
--resources-vpc-config subnetIds=subnet-12345,subnet-67890,securityGroupIds=sg-12345
# Specifying custom security groups using eksctl
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: us-west-2
vpc:
id: vpc-12345
securityGroup: sg-12345
subnets:
private:
us-west-2a: subnet-12345
us-west-2b: subnet-67890Security Groups for Pods:
Recently, EKS also supports pod-level security groups (SecurityGroupsForPods feature). This allows you to apply security groups to individual pods:
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: my-security-group-policy
namespace: default
spec:
podSelector:
matchLabels:
app: my-app
securityGroups:
groupIds:
- sg-12345Issues with Other Options:
- Controlling network traffic between pods: By default, network traffic between pods is controlled through Kubernetes Network Policies (NetworkPolicy), not AWS security groups. While the SecurityGroupsForPods feature allows applying security groups at the pod level, this is not the primary role of security groups.
- Applying Kubernetes RBAC policies: RBAC (Role-Based Access Control) is a mechanism for controlling access to Kubernetes API resources and is separate from AWS security groups.
- Managing user authentication: User authentication in EKS clusters is managed through the integration of AWS IAM and Kubernetes RBAC, and is unrelated to security groups.
Security groups play an important role in network security of EKS clusters, protecting communication between cluster components and blocking unnecessary traffic. Proper security group configuration is essential for strengthening the security posture of EKS clusters.
- What is required to implement Kubernetes Network Policies in an Amazon EKS cluster?
- A) AWS security group configuration
- B) A CNI plugin that supports network policies, such as Calico or Cilium
- C) AWS Network Firewall setup
- D) VPC Flow Logs enabled
Show Answer
Answer: B) A CNI plugin that supports network policies, such as Calico or Cilium
Explanation: To implement Kubernetes Network Policies in an Amazon EKS cluster, you need a CNI (Container Network Interface) plugin that supports network policies, such as Calico or Cilium. The default Amazon VPC CNI plugin does not support network policies, so additional components must be installed.
CNI Options with Network Policy Support:
- Calico:
Widely used open-source networking and network security solution
Can be used alongside Amazon VPC CNI in EKS
Installation method:
bash# Install Calico using Helm helm repo add projectcalico https://docs.projectcalico.org/charts helm install calico projectcalico/tigera-operator --namespace tigera-operator --create-namespace # Or install using manifest files kubectl apply -f https://docs.projectcalico.org/manifests/calico-vxlan.yaml
- Cilium:
eBPF-based networking, security, and observability solution
Provides high performance and advanced features
Installation method:
bash# Install Cilium using Helm helm repo add cilium https://helm.cilium.io/ helm install cilium cilium/cilium --namespace kube-system
- AWS CNI with Cilium:
A hybrid approach using Amazon VPC CNI and Cilium together
VPC CNI handles pod networking, and Cilium handles network policies
Installation method:
bash# Install Cilium in network policy only mode helm install cilium cilium/cilium --namespace kube-system \ --set enableIPv4Masquerade=false \ --set tunnel=disabled \ --set installIptablesRules=false \ --set autoDirectNodeRoutes=false \ --set policyEnforcementMode=default
Network Policy Examples:
# Default deny policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# Allow communication between specific applications
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080Verifying Network Policy Implementation:
# Verify network policy support
kubectl get pods -n kube-system | grep -E 'calico|cilium'
# Apply test network policy
kubectl apply -f test-network-policy.yaml
# Test connectivity
kubectl run -it --rm --restart=Never busybox --image=busybox -- wget -O- --timeout=2 http://service-nameIssues with Other Options:
- AWS security group configuration: AWS security groups operate at the EC2 instance level and cannot be used to implement fine-grained network policies between Kubernetes pods. While the SecurityGroupsForPods feature allows applying security groups to pods, this is a different mechanism from Kubernetes NetworkPolicy.
- AWS Network Firewall setup: AWS Network Firewall operates at the VPC level and cannot be used to implement fine-grained network policies between Kubernetes pods.
- VPC Flow Logs enabled: VPC Flow Logs are used for monitoring and logging network traffic, but cannot be used to implement network policies.
Network policies are an important tool for controlling communication between microservices and enhancing security within Kubernetes clusters. To implement network policies in EKS, you must install additional CNI plugins such as Calico or Cilium.
- What is the correct way to configure Secrets encryption in an Amazon EKS cluster?
- A) Enable encryption using an AWS KMS key when creating the EKS cluster
- B) Migrate Kubernetes Secrets to AWS Secrets Manager
- C) Encode all Secrets in Base64
- D) Deploy an encryption sidecar container to the EKS cluster
Show Answer
Answer: A) Enable encryption using an AWS KMS key when creating the EKS cluster
Explanation: The correct way to configure Secrets encryption in an Amazon EKS cluster is to enable encryption using an AWS KMS (Key Management Service) key when creating the EKS cluster or on an existing cluster. This method ensures that Kubernetes Secrets are encrypted when stored in etcd.
Steps to Configure EKS Secrets Encryption:
Create a KMS Key or Use an Existing Key:
bash# Create KMS key aws kms create-key --description "EKS Secrets Encryption Key" # Store the created key ID KEY_ID=$(aws kms create-key --query KeyMetadata.KeyId --output text)Enable Encryption When Creating a New Cluster:
bash# Enable encryption using AWS CLI aws eks create-cluster \ --name my-cluster \ --role-arn arn:aws:iam::123456789012:role/EksClusterRole \ --resources-vpc-config subnetIds=subnet-12345,subnet-67890 \ --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws:kms:region:123456789012:key/'$KEY_ID'"}}]' # Enable encryption using eksctl cat > cluster.yaml << EOF apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster region: us-west-2 secretsEncryption: keyARN: arn:aws:kms:us-west-2:123456789012:key/$KEY_ID EOF eksctl create cluster -f cluster.yamlEnable Encryption on an Existing Cluster:
bash# For existing clusters, you cannot update the encryption configuration, so you need to create a new cluster and migrate workloads.Verify Encryption Configuration:
bash# Check cluster information aws eks describe-cluster --name my-cluster --query cluster.encryptionConfig
Using Encrypted Secrets:
Once encryption is enabled, the method for creating and using Secrets does not change. All encryption and decryption is handled automatically by the EKS control plane.
# Create Secret
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: YWRtaW4= # base64 encoded "admin"
password: cGFzc3dvcmQ= # base64 encoded "password"# Create Secret
kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=password
# Verify Secret
kubectl get secret my-secret -o yamlConfiguring KMS Key Permissions:
You need to configure appropriate permissions so that the EKS cluster can use the KMS key:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEKSToUseKMSKey",
"Effect": "Allow",
"Principal": {
"Service": "eks.amazonaws.com"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
}
]
}Issues with Other Options:
- Migrate Kubernetes Secrets to AWS Secrets Manager: This is a possible approach, but it has less compatibility with the standard Kubernetes Secrets API and requires additional configuration and integration. Also, all applications need to be modified to retrieve secrets from AWS Secrets Manager.
- Encode all Secrets in Base64: Kubernetes Secrets are already Base64 encoded by default. However, Base64 is an encoding method, not encryption, and does not provide security.
- Deploy an encryption sidecar container to the EKS cluster: This is not a standard approach, and adding sidecars to all pods introduces complexity. It also requires integration with the Kubernetes API server.
EKS Secrets encryption using AWS KMS is the most effective and integrated way to protect Secrets stored in etcd. This allows you to protect sensitive data at rest and leverage AWS's powerful key management capabilities.
5. What is the correct way to customize kubelet configuration for worker nodes in an Amazon EKS cluster? - A) Modify cluster configuration in the EKS console - B) Use the --kubelet-extra-args parameter when creating the node group - C) Use the kubectl edit node command - D) Use AWS Systems Manager to change node configuration
Show Answer
Answer: B) Use the --kubelet-extra-args parameter when creating the node group
Explanation: The correct way to customize kubelet configuration for worker nodes in an Amazon EKS cluster is to use the --kubelet-extra-args parameter when creating the node group. This method allows you to pass additional arguments to kubelet when the node is bootstrapped.
Methods to Customize kubelet Configuration:
Using Launch Templates with Managed Node Groups:
- Customize the bootstrap script in the user data section of the launch template.
bash#!/bin/bash set -o xtrace /etc/eks/bootstrap.sh my-cluster \ --kubelet-extra-args '--max-pods=110 --kube-reserved memory=0.3Gi,cpu=100m --system-reserved memory=0.5Gi,cpu=200m --eviction-hard memory.available<500Mi'Creating Node Groups Using eksctl:
# Create node group with kubelet arguments
eksctl create nodegroup \
--cluster my-cluster \
--name my-nodegroup \
--node-type m5.large \
--nodes 3 \
--kubelet-extra-args "--max-pods=110 --kube-reserved memory=0.3Gi,cpu=100m"Using eksctl configuration file:
yamlapiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster region: us-west-2 managedNodeGroups: - name: my-nodegroup instanceType: m5.large minSize: 2 maxSize: 5 kubeletExtraArgs: max-pods: "110" kube-reserved: "memory=0.3Gi,cpu=100m" system-reserved: "memory=0.5Gi,cpu=200m" eviction-hard: "memory.available<500Mi"Using user data script for self-managed node groups:
bash#!/bin/bash set -o xtrace /etc/eks/bootstrap.sh my-cluster \ --kubelet-extra-args '--max-pods=110 --node-labels=node.kubernetes.io/role=worker,environment=prod'
Commonly customized kubelet parameters:
- max-pods:
- Sets the maximum number of pods per node
- Example:
--max-pods=110
- node-labels:
- Adds labels to the node
- Example:
--node-labels=environment=prod,node-type=worker
- kube-reserved:
- Reserves resources for Kubernetes system components
- Example:
--kube-reserved=cpu=100m,memory=0.3Gi,ephemeral-storage=1Gi
- system-reserved:
- Reserves resources for OS system daemons
- Example:
--system-reserved=cpu=100m,memory=0.5Gi,ephemeral-storage=1Gi
- eviction-hard:
- Sets hard eviction thresholds
- Example:
--eviction-hard=memory.available<500Mi,nodefs.available<10%
- cgroup-driver:
- Sets the cgroup driver
- Example:
--cgroup-driver=systemd
How to verify the configuration:
# SSH into the node
ssh -i ~/.ssh/id_rsa ec2-user@<node-ip>
# Check kubelet service configuration
sudo systemctl status kubelet
sudo cat /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf
# Check running kubelet process arguments
ps aux | grep kubeletIssues with other options:
- Modifying cluster configuration in EKS console: While the EKS console allows you to modify cluster-level configurations, it does not provide options to directly modify the kubelet configuration of individual nodes.
- Using kubectl edit node command: The
kubectl edit nodecommand can modify node object metadata, but it cannot change kubelet configuration. The kubelet configuration runs as a service on the node OS and cannot be directly modified through the Kubernetes API. - Using AWS Systems Manager to change node configuration: AWS Systems Manager can be used to run commands or change configurations on nodes, but this method is applied after the nodes are already created. Additionally, after changing the kubelet configuration, the service must be restarted, which can affect running pods. Therefore, configuring at node group creation time is safer and the recommended approach.
Customizing kubelet configuration allows you to optimize node resource management, pod density, eviction policies, and more to meet your workload requirements. However, changes should be tested carefully as they can affect cluster stability.
- What is the recommended mechanism to replace Pod Security Policy in Amazon EKS clusters?
- A) AWS Security Hub
- B) Pod Security Admission or policy engines like Kyverno
- C) AWS Config Rules
- D) EKS Security Groups
Show Answer
Answer: B) Pod Security Admission or policy engines like Kyverno
Explanation: The recommended mechanism to replace Pod Security Policy (PSP) in Amazon EKS clusters is Pod Security Admission or policy engines like Kyverno. Starting from Kubernetes 1.21, PSP was deprecated, and it was completely removed in Kubernetes 1.25. Pod Security Admission was introduced as a replacement, and policy engines like Kyverno or OPA Gatekeeper can also be used as alternatives.
Pod Security Admission:
Pod Security Admission was introduced as a beta feature starting from Kubernetes 1.23 and became stable in version 1.25. It is a built-in Kubernetes feature that provides three security levels (Privileged, Baseline, Restricted).
Configuration method:
yaml# Apply Pod Security standards to namespace apiVersion: v1 kind: Namespace metadata: name: my-namespace labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/warn: restrictedSecurity levels:
- Privileged: No restrictions, all features allowed
- Baseline: Prevents known privilege escalations
- Restricted: Strong security hardening, applies principle of least privilege
Modes:
- enforce: Rejects pod creation on violation
- audit: Records violations in audit logs
- warn: Displays warning messages on violation
Kyverno:
Kyverno is a Kubernetes-native policy engine that uses YAML-based policies to validate, mutate, and generate cluster resources.
Installation method:
bash# Install Kyverno using Helm helm repo add kyverno https://kyverno.github.io/kyverno/ helm install kyverno kyverno/kyverno --namespace kyverno --create-namespacePolicy example:
yaml# Policy to prevent privileged containers apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-privileged-containers spec: validationFailureAction: enforce rules: - name: privileged-containers match: resources: kinds: - Pod validate: message: "Privileged containers are not allowed" pattern: spec: containers: - name: "*" securityContext: privileged: false
OPA Gatekeeper:
OPA (Open Policy Agent) Gatekeeper is another popular solution for policy management in Kubernetes.
Installation method:
bash# Install Gatekeeper kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yamlPolicy example:
yaml# ConstraintTemplate definition apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spsprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spsprivilegedcontainer violation[{"msg": msg}] { c := input.review.object.spec.containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v", [c.name]) } # Apply Constraint apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: match: kinds: - apiGroups: [""] kinds: ["Pod"]
Implementation recommendations for EKS:
- Enable Pod Security Admission:
- Available by default in EKS 1.23 and above
- Apply appropriate labels to namespaces
- Install Kyverno or Gatekeeper:
- When more complex policies are needed
- When policies for multiple resource types are required
- Gradual migration:
- Gradually migrate from PSP to new solutions
- Start in audit mode to identify issues, then switch to enforce mode
Issues with other options:
- AWS Security Hub: AWS Security Hub is a service for monitoring the security posture of AWS resources, but it cannot be used to apply pod-level security policies in Kubernetes.
- AWS Config Rules: AWS Config is a service for evaluating AWS resource configurations, but it cannot be used to apply pod-level security policies in Kubernetes.
- EKS Security Groups: EKS Security Groups are used to control network traffic and cannot be used to restrict pod security contexts or privileges.
With the removal of Pod Security Policy (PSP), EKS clusters should use alternative mechanisms such as Pod Security Admission, Kyverno, or OPA Gatekeeper to strengthen pod security. These tools can restrict privileged containers, host namespace access, host path mounts, and more.
7. What is the first step in configuring IRSA (IAM Roles for Service Accounts) to integrate pod identity with AWS IAM in an Amazon EKS cluster? - A) Create an IAM role - B) Create a service account - C) Associate an OIDC provider - D) Modify the pod manifest
Show Answer
Answer: C) Associate an OIDC provider
Explanation: The first step in configuring IRSA (IAM Roles for Service Accounts) in an Amazon EKS cluster is to associate an OIDC (OpenID Connect) provider. The OIDC provider is required to establish a trust relationship between AWS IAM and Kubernetes service accounts. This allows Kubernetes service account tokens to become a trusted authentication mechanism in AWS IAM.
IRSA configuration steps in order:
Associate OIDC provider:
- Check the EKS cluster's OIDC issuer URL
- Create OIDC provider in AWS IAM
bash# Check OIDC issuer URL aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text # Example output: https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE # Associate OIDC provider eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve # Or use AWS CLI aws iam create-open-id-connect-provider \ --url https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE \ --thumbprint-list 9e99a48a9960b14926bb7f3b02e22da2b0ab7280 \ --client-id-list sts.amazonaws.comCreate IAM role:
- Create the IAM role that the service account will assume
- Include OIDC provider and service account conditions in the trust policy
json{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-service-account" } } } ] }Create service account:
- Create a service account with the IAM role ARN as an annotation
yamlapiVersion: v1 kind: ServiceAccount metadata: name: my-service-account namespace: default annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-roleModify pod manifest:
- Specify the service account in the pod manifest
yamlapiVersion: v1 kind: Pod metadata: name: my-pod spec: serviceAccountName: my-service-account containers: - name: my-container image: my-image
Simplified IRSA setup using eksctl:
eksctl provides commands that automate all of the above steps:
# Associate OIDC provider
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve
# Create service account and IAM role
eksctl create iamserviceaccount \
--name my-service-account \
--namespace default \
--cluster my-cluster \
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approveVerify IRSA is working:
# Check service account
kubectl get serviceaccount my-service-account -o yaml
# Run test pod
kubectl run -it --rm \
--image amazon/aws-cli \
--serviceaccount my-service-account \
aws-cli -- s3 lsIssues with other options:
- Create an IAM role: Creating an IAM role is the second step in IRSA configuration. The OIDC provider must be associated first so that the IAM role's trust policy can reference the OIDC provider.
- Create a service account: Creating a service account is the third step in IRSA configuration. The IAM role must be created first so that the IAM role ARN can be added as an annotation to the service account.
- Modify the pod manifest: Modifying the pod manifest is the last step in IRSA configuration. The service account must be created first so that the pod can reference that service account.
IRSA is a secure and efficient way to grant Kubernetes workloads fine-grained permissions to AWS services. This allows you to grant each application only the minimum required permissions instead of sharing node-level IAM roles. The first step in IRSA configuration is to associate an OIDC provider, which is essential for establishing the trust relationship between AWS IAM and Kubernetes service accounts.
- What is the correct way to enable control plane logs in an Amazon EKS cluster?
- A) Install CloudWatch agent on EKS control plane
- B) Enable cluster logging configuration via AWS CLI or console
- C) Configure log forwarding using Fluentd
- D) SSH into EKS control plane nodes to modify log configuration
Show Answer
Answer: B) Enable cluster logging configuration via AWS CLI or console
Explanation: The correct way to enable control plane logs in an Amazon EKS cluster is to enable the cluster logging configuration via AWS CLI or AWS Management Console. Since EKS is a managed service and the control plane is managed by AWS, you cannot directly access it or install agents. Instead, you must configure logging through AWS-provided APIs.
Enable control plane logs using AWS CLI:
# Enable all log types
aws eks update-cluster-config \
--name my-cluster \
--region us-west-2 \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
# Enable only specific log types
aws eks update-cluster-config \
--name my-cluster \
--region us-west-2 \
--logging '{"clusterLogging":[{"types":["api","audit"],"enabled":true},{"types":["authenticator","controllerManager","scheduler"],"enabled":false}]}'Enable control plane logs using eksctl:
# Enable all log types
eksctl utils update-cluster-logging \
--enable-types api,audit,authenticator,controllerManager,scheduler \
--cluster my-cluster \
--region us-west-2
# Enable only specific log types
eksctl utils update-cluster-logging \
--enable-types api,audit \
--disable-types authenticator,controllerManager,scheduler \
--cluster my-cluster \
--region us-west-2Enable control plane logs using AWS Management Console:
- Log in to the AWS Management Console.
- Navigate to the EKS service.
- Select the target cluster from the cluster list.
- Select the "Logging" tab.
- Click "Manage".
- Select the log types to enable:
- API server (api)
- Audit (audit)
- Authenticator (authenticator)
- Controller manager (controllerManager)
- Scheduler (scheduler)
- Click "Save changes".
Available log types:
- API server (api):
- Logs from the Kubernetes API server
- Contains API request and response information
- Audit (audit):
- Audit logs for all activities in the cluster
- Important for security and compliance purposes
- Authenticator (authenticator):
- Logs from AWS IAM Authenticator
- Useful for troubleshooting authentication issues
- Controller manager (controllerManager):
- Logs from the Kubernetes controller manager
- Contains resource state management information
- Scheduler (scheduler):
- Logs from the Kubernetes scheduler
- Contains information about pod scheduling decisions
How to view logs:
Enabled logs are stored in CloudWatch Logs and can be viewed in the following log group:
/aws/eks/my-cluster/clusterEach log type is stored as a separate log stream:
kube-apiserver-xxxxx
audit-xxxxx
authenticator-xxxxx
kube-controller-manager-xxxxx
kube-scheduler-xxxxxCost considerations:
- Control plane logs are subject to CloudWatch Logs pricing.
- Enabling all log types can generate a significant amount of logs.
- For cost optimization, it is recommended to selectively enable only the log types you need.
- You can manage costs by setting appropriate log retention periods.
Issues with other options:
- Install CloudWatch agent on EKS control plane: The EKS control plane is managed by AWS, so you cannot directly access it or install agents.
- Configure log forwarding using Fluentd: Fluentd can be used to collect logs from worker nodes, but it cannot access EKS control plane logs.
- SSH into EKS control plane nodes to modify log configuration: EKS control plane nodes are managed by AWS, so you cannot SSH into them directly.
EKS control plane logs provide important information for cluster troubleshooting, security audits, and compliance. You can effectively monitor by selectively enabling the required log types through AWS CLI or AWS Management Console.
- What is the correct way to change the instance type of a node group in an Amazon EKS cluster?
- A) Directly modify node group instance type in AWS Management Console
- B) Create a new node group with the new instance type and migrate workloads
- C) Modify node specifications with kubectl edit command
- D) Use AWS CLI update-nodegroup-config command
Show Answer
Answer: B) Create a new node group with the new instance type and migrate workloads
Explanation: The correct way to change the instance type of a node group in an Amazon EKS cluster is to create a new node group with the new instance type and then migrate workloads. In EKS managed node groups, you cannot directly change the instance type after creation, so you must create a new node group, migrate workloads, and then delete the existing node group.
Steps to change node group instance type:
Create new node group:
bash# Create new node group using eksctl eksctl create nodegroup \ --cluster my-cluster \ --name my-new-nodegroup \ --node-type m5.large \ --nodes 3 \ --nodes-min 1 \ --nodes-max 5 \ --node-labels "migration-target=true"
Create new node group using AWS CLI
aws eks create-nodegroup
--cluster-name my-cluster
--nodegroup-name my-new-nodegroup
--subnets subnet-12345 subnet-67890
--instance-types m5.large
--scaling-config minSize=1,maxSize=5,desiredSize=3
--node-role arn:aws:iam::123456789012:role/EksNodeRole
--labels migration-target=true
2. **Verify new node group status**:
```bash
# Check node group status
aws eks describe-nodegroup \
--cluster-name my-cluster \
--nodegroup-name my-new-nodegroup \
--query "nodegroup.status"
# Check nodes
kubectl get nodes --label-columns migration-targetMigrate workloads:
Method 1: Using Cordoning and Draining
bash# Identify nodes in the existing node group OLD_NODES=$(kubectl get nodes -l alpha.eksctl.io/nodegroup-name=my-old-nodegroup -o jsonpath='{.items[*].metadata.name}') # Cordon nodes (prevent new pod scheduling) for node in $OLD_NODES; do kubectl cordon $node done # Drain nodes (remove existing pods) for node in $OLD_NODES; do kubectl drain $node --ignore-daemonsets --delete-emptydir-data doneMethod 2: Using Pod Selector
yaml# Deploy to new nodes using node selector apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: template: spec: nodeSelector: migration-target: "true"Method 3: Blue/Green Deployment
- Deploy new deployment version to the new node group
- Gradually shift traffic to the new version
- Remove the existing deployment version
Delete existing node group:
bash# Delete node group using eksctl eksctl delete nodegroup \ --cluster my-cluster \ --name my-old-nodegroup # Delete node group using AWS CLI aws eks delete-nodegroup \ --cluster-name my-cluster \ --nodegroup-name my-old-nodegroup
Considerations during migration:
Minimize workload disruption:
- Configure PodDisruptionBudget
yamlapiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: my-app-pdb spec: minAvailable: 2 # or maxUnavailable: 1 selector: matchLabels: app: my-app- Use rolling update strategy
Resource requirements:
- Verify that the new instance type meets workload requirements
- Consider CPU, memory, storage, and networking requirements
Stateful workloads:
- Verify data persistence for workloads using persistent volumes
- Perform backups if necessary
Cost impact:
- Evaluate the cost impact of the new instance type
- Costs increase temporarily as both node groups run simultaneously during migration
Problems with other options:
- Directly modifying node group instance type in AWS Management Console: In EKS managed node groups, you cannot directly modify the instance type after creation.
- Modifying node specifications with kubectl edit command: kubectl is used to modify Kubernetes API objects, but the underlying instance type of a node is determined at the AWS infrastructure level and cannot be changed through kubectl.
- Using AWS CLI update-nodegroup-config command: The
update-nodegroup-configcommand can modify the node group's scaling configuration, labels, taints, etc., but cannot change the instance type.
Changing the instance type of a node group may be necessary for optimizing cluster performance, reducing costs, or meeting new workload requirements. Creating a new node group and migrating workloads is the recommended approach to safely change instance types while minimizing disruption.
10. What is the correct way to apply Kubernetes taints to a node group in an Amazon EKS cluster? - A) Use kubectl taint command - B) Use --taints parameter when creating node group - C) Configure node group taints in AWS Management Console - D) Modify kubelet configuration in node bootstrap script
Show Answer
Answer: B) Use --taints parameter when creating node group
Explanation: The correct way to apply Kubernetes taints to a node group in an Amazon EKS cluster is to use the --taints parameter when creating the node group. EKS managed node groups provide the ability to configure taints at creation time or during updates. Using this method ensures that taints are consistently applied to all nodes in the node group and are maintained when nodes are replaced.
Configuring taints using eksctl:
# Create node group with taints
eksctl create nodegroup \
--cluster my-cluster \
--name tainted-ng \
--node-type m5.large \
--nodes 3 \
--taints "dedicated=gpu:NoSchedule,special=true:PreferNoSchedule"
# Configure taints using configuration file
cat > nodegroup.yaml << EOF
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: us-west-2
managedNodeGroups:
- name: tainted-ng
instanceType: m5.large
minSize: 2
maxSize: 5
taints:
- key: dedicated
value: gpu
effect: NoSchedule
- key: special
value: "true"
effect: PreferNoSchedule
EOF
eksctl create nodegroup -f nodegroup.yamlConfiguring taints using AWS CLI:
# Create node group with taints
aws eks create-nodegroup \
--cluster-name my-cluster \
--nodegroup-name tainted-ng \
--subnets subnet-12345 subnet-67890 \
--instance-types m5.large \
--scaling-config minSize=2,maxSize=5,desiredSize=3 \
--node-role arn:aws:iam::123456789012:role/EksNodeRole \
--taints "key=dedicated,value=gpu,effect=NoSchedule" "key=special,value=true,effect=PreferNoSchedule"
# Update taints on existing node group
aws eks update-nodegroup-config \
--cluster-name my-cluster \
--nodegroup-name tainted-ng \
--taints "addOrUpdateTaints=[{key=dedicated,value=gpu,effect=NoSchedule}],removeTaints=[{key=special}]"Configuring taints using AWS Management Console:
- Log in to the AWS Management Console.
- Navigate to the EKS service.
- Select the cluster.
- Select the "Compute" tab.
- Click "Add node group".
- Enter the node group details.
- In the "Kubernetes taints" section, click "Add taint".
- Enter the key, value, and effect.
- Click "Create".
Taint effect types:
- NoSchedule:
- Pods without a matching toleration for the taint will not be scheduled on the node.
- Existing pods are not affected.
- PreferNoSchedule:
- Pods without a matching toleration for the taint will preferably not be scheduled on the node, but this is not guaranteed.
- If they cannot be scheduled on other nodes, they may be scheduled on this node.
- NoExecute:
- Pods without a matching toleration for the taint will not be scheduled on the node.
- Pods already running that do not have a matching toleration for the taint will be evicted.
Common use cases for taints:
Isolating special hardware nodes:
bash# Apply taint to GPU nodes eksctl create nodegroup \ --cluster my-cluster \ --name gpu-nodes \ --node-type p3.2xlarge \ --taints "dedicated=gpu:NoSchedule" # Add toleration to GPU workload apiVersion: v1 kind: Pod metadata: name: gpu-pod spec: tolerations: - key: "dedicated" operator: "Equal" value: "gpu" effect: "NoSchedule" containers: - name: gpu-container image: gpu-imagePreparing for node maintenance:
bash# Apply taint to node kubectl taint nodes node1 maintenance=planned:NoSchedule # Remove taint after maintenance kubectl taint nodes node1 maintenance=planned:NoSchedule-Configuring dedicated nodes for specific workloads:
bash# Node group dedicated to production workloads eksctl create nodegroup \ --cluster my-cluster \ --name prod-nodes \ --node-type m5.large \ --taints "environment=production:NoSchedule" # Add toleration to production deployment apiVersion: apps/v1 kind: Deployment metadata: name: prod-app spec: template: spec: tolerations: - key: "environment" operator: "Equal" value: "production" effect: "NoSchedule"
Problems with other options:
- Using kubectl taint command: You can use the
kubectl taintcommand to apply taints to individual nodes, but this is a temporary change and taints are not maintained when nodes are replaced. It is also difficult to apply consistently to all nodes in a node group. - Configuring node group taints in AWS Management Console: You can also configure taints when creating a node group in the AWS Management Console, but this is the same approach as "using --taints parameter when creating node group". Therefore, this option could be a correct answer, but technically it is the same as configuring taints when creating a node group.
- Modifying kubelet configuration in node bootstrap script: You can modify the kubelet configuration using the
--register-with-taintsflag in the bootstrap script, but this is a complex and error-prone method. It is also not recommended for EKS managed node groups.
Taints are a useful Kubernetes feature for deploying specific workloads only to specific nodes or excluding certain workloads from specific nodes. For EKS managed node groups, configuring taints when creating or updating the node group is the most effective and manageable method.
Hands-on Exercises
Exercise 1: Configuring IRSA (IAM Roles for Service Accounts)
Scenario: You have an application running in an EKS cluster that needs to access an S3 bucket. Following security best practices, you want to use IRSA to grant only the necessary permissions to specific pods instead of sharing the node IAM role.
Requirements:
- Associate OIDC provider
- Create IAM role with S3 access permissions
- Create service account and associate IAM role
- Deploy pod using the service account
- Test S3 access
Solution:
Show Solution
1. Associate OIDC Provider
# Get the cluster's OIDC issuer URL
OIDC_PROVIDER=$(aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")
# Check if OIDC provider already exists
aws iam list-open-id-connect-providers | grep $OIDC_PROVIDER
# Create OIDC provider if it doesn't exist
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve2. Create IAM Role with S3 Access Permissions
# Create trust policy
cat > trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:sub": "system:serviceaccount:default:s3-access-sa"
}
}
}
]
}
EOF
# Create IAM role
aws iam create-role --role-name s3-access-role --assume-role-policy-document file://trust-policy.json
# Attach S3 access policy
aws iam attach-role-policy --role-name s3-access-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess3. Create Service Account and Associate IAM Role
# Get IAM role ARN
ROLE_ARN=$(aws iam get-role --role-name s3-access-role --query Role.Arn --output text)
# Create service account
cat > service-account.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: s3-access-sa
namespace: default
annotations:
eks.amazonaws.com/role-arn: ${ROLE_ARN}
EOF
kubectl apply -f service-account.yaml4. Deploy Pod Using the Service Account
# Deploy test pod
cat > pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: s3-access-pod
namespace: default
spec:
serviceAccountName: s3-access-sa
containers:
- name: aws-cli
image: amazon/aws-cli:latest
command:
- sleep
- "3600"
restartPolicy: Never
EOF
kubectl apply -f pod.yaml5. Test S3 Access
# Verify the pod is running
kubectl get pod s3-access-pod
# Test listing S3 buckets
kubectl exec -it s3-access-pod -- aws s3 ls
# Test listing objects in a specific S3 bucket
kubectl exec -it s3-access-pod -- aws s3 ls s3://my-bucket
# Verify AWS credentials
kubectl exec -it s3-access-pod -- aws sts get-caller-identity6. Cleanup
# Delete pod
kubectl delete pod s3-access-pod
# Delete service account
kubectl delete serviceaccount s3-access-sa
# Clean up IAM role
aws iam detach-role-policy --role-name s3-access-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam delete-role --role-name s3-access-roleAdditional Explanation:
- OIDC Provider Association:
- The OIDC provider establishes a trust relationship between AWS IAM and Kubernetes service accounts.
- This only needs to be set up once per cluster.
- IAM Role Trust Policy:
- The trust policy restricts only specific service accounts in specific namespaces to assume the role.
- Security is enhanced using condition statements.
- Service Account Annotation:
- The
eks.amazonaws.com/role-arnannotation specifies the IAM role that the service account will assume. - This annotation is processed by the EKS Pod Identity Webhook.
- The
- Environment Variables:
- The EKS Pod Identity Webhook automatically injects the following environment variables into the pod:
AWS_ROLE_ARNAWS_WEB_IDENTITY_TOKEN_FILEAWS_REGION
- AWS SDKs use these environment variables to obtain credentials.
- The EKS Pod Identity Webhook automatically injects the following environment variables into the pod:
- Principle of Least Privilege:
- Grant only the minimum permissions required by the application.
- In this example, only S3 read-only access permission was granted.
Through this exercise, you learned how to configure IRSA to grant fine-grained permissions to AWS services only to specific pods running in an EKS cluster. This approach is more secure than sharing the node IAM role and follows the principle of least privilege.
### Exercise 2: Strengthening EKS Cluster Security
Scenario: You are a security engineer at your company and need to strengthen the security of a newly created EKS cluster. The cluster is already created and configured with default settings. You want to harden the cluster according to security best practices.
Requirements:
- Restrict cluster endpoint access
- Enable Secrets encryption
- Implement network policies
- Apply Pod Security Standards
- Enable control plane logging
Solution:
Show Solution
1. Restrict Cluster Endpoint Access
# Check current cluster endpoint configuration
aws eks describe-cluster --name my-cluster --query "cluster.resourcesVpcConfig.endpointPublicAccess"
aws eks describe-cluster --name my-cluster --query "cluster.resourcesVpcConfig.endpointPrivateAccess"
# Restrict public access (allow only specific CIDR blocks)
aws eks update-cluster-config \
--name my-cluster \
--resources-vpc-config endpointPublicAccess=true,endpointPrivateAccess=true,publicAccessCidrs=["203.0.113.0/24","198.51.100.0/24"]
# Or disable public access (private cluster)
aws eks update-cluster-config \
--name my-cluster \
--resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true2. Enable Secrets Encryption
# Create KMS key
aws kms create-key --description "EKS Secrets Encryption Key"
KEY_ID=$(aws kms create-key --query KeyMetadata.KeyId --output text)
# Add alias to KMS key
aws kms create-alias \
--alias-name alias/eks-secrets \
--target-key-id $KEY_ID
# Cannot enable encryption on current cluster, so a new cluster must be created
# Get existing cluster configuration
aws eks describe-cluster --name my-cluster > cluster-config.json
# Create new cluster (more parameters are needed in practice)
aws eks create-cluster \
--name my-cluster-encrypted \
--role-arn $(aws eks describe-cluster --name my-cluster --query cluster.roleArn --output text) \
--resources-vpc-config subnetIds=$(aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.subnetIds --output text | tr -d '[]" ' | tr ',' ' '),securityGroupIds=$(aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.securityGroupIds --output text | tr -d '[]" ') \
--encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws:kms:'$(aws configure get region)':'$(aws sts get-caller-identity --query Account --output text)':key/'$KEY_ID'"}}]'3. Implement Network Policies
# Install Calico
kubectl create namespace tigera-operator
helm repo add projectcalico https://docs.projectcalico.org/charts
helm install calico projectcalico/tigera-operator --namespace tigera-operator
# Create default deny network policy
cat > default-deny.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
kubectl apply -f default-deny.yaml
# Policy to allow communication between specific applications
cat > allow-app-communication.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
EOF
kubectl apply -f allow-app-communication.yaml4. Apply Pod Security Standards
# Apply Pod Security Standards to namespace
cat > pod-security.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
name: restricted-ns
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
EOF
kubectl apply -f pod-security.yaml
# Add labels to existing namespace
kubectl label namespace default \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
# Install Kyverno (for additional policy enforcement)
kubectl create namespace kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno --namespace kyverno
# Policy to prevent privileged containers
cat > restrict-privileged.yaml << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
spec:
validationFailureAction: enforce
rules:
- name: privileged-containers
match:
resources:
kinds:
- Pod
validate:
message: "Privileged containers are not allowed"
pattern:
spec:
containers:
- name: "*"
securityContext:
privileged: false
EOF
kubectl apply -f restrict-privileged.yaml5. Enable Control Plane Logging
# Enable all control plane log types
aws eks update-cluster-config \
--name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
# Verify logging status
aws eks describe-cluster --name my-cluster --query "cluster.logging"
# Check logs in CloudWatch Logs
aws logs describe-log-groups --log-group-name-prefix /aws/eks/my-cluster6. Additional Security Hardening Measures
# Restrict IAM policy for AWS Load Balancer Controller
cat > alb-controller-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeListeners"
],
"Resource": "*"
}
]
}
EOF
aws iam create-policy \
--policy-name EksAlbControllerRestrictedPolicy \
--policy-document file://alb-controller-policy.json
# Configure node group update for periodic node replacement
aws eks update-nodegroup-config \
--cluster-name my-cluster \
--nodegroup-name my-nodegroup \
--update-config '{"maxUnavailable": 1}'
# Start node group update
aws eks update-nodegroup-version \
--cluster-name my-cluster \
--nodegroup-name my-nodegroupSecurity Hardening Explanation:
- Restrict Cluster Endpoint Access:
- Restrict public endpoint access to specific IP ranges or disable it entirely.
- Enable private endpoint to allow cluster access from within the VPC.
- This prevents unauthorized access to the cluster API server.
- Enable Secrets Encryption:
- Use AWS KMS keys to encrypt Kubernetes Secrets stored in etcd.
- Protects sensitive data at rest.
- Note: Encryption cannot be enabled on existing clusters, so you need to create a new cluster.
- Implement Network Policies:
- Install Calico to support Kubernetes network policies.
- Apply default deny policies to block all traffic not explicitly allowed.
- Implement fine-grained policies that allow only necessary communication.
- Apply Pod Security Standards:
- Apply Pod Security Standards available in Kubernetes 1.23 and later.
- Set security constraints at the namespace level.
- Use policy engines like Kyverno to apply additional security policies.
- Enable Control Plane Logging:
- Send all control plane log types to CloudWatch Logs.
- Monitor cluster activity through audit logs.
- Maintain logs for security events and troubleshooting.
Through this hands-on exercise, you learned various methods to strengthen the security of your EKS cluster. These security measures help improve your cluster's security posture and protect it from unauthorized access and malicious activities.
Advanced Topics
The following are questions about advanced topics in Amazon EKS cluster creation. This section tests your understanding of advanced concepts and best practices in EKS cluster creation.
- Which of the following is NOT a requirement for configuring IPv6 support in an Amazon EKS cluster?
- A) VPC with an assigned IPv6 CIDR block
- B) CNI plugin version that supports IPv6
- C) Dual-stack subnets
- D) IPv6-only instance types
Show Answer
Answer: D) IPv6-only instance types
Explanation: "IPv6-only instance types" is NOT a requirement for configuring IPv6 support in an Amazon EKS cluster. There are no special instance types required for IPv6 support, as most EC2 instance types support IPv6. The actual requirements are a VPC with an assigned IPv6 CIDR block, a CNI plugin version that supports IPv6, and dual-stack subnets.
Actual Requirements for IPv6 Support in EKS:
VPC with an assigned IPv6 CIDR block:
- You must assign an IPv6 CIDR block to your VPC.
- This can be configured through the AWS Management Console or AWS CLI.
bash# Assign IPv6 CIDR block to existing VPC aws ec2 associate-vpc-cidr-block \ --vpc-id vpc-12345 \ --amazon-provided-ipv6-cidr-blockCNI plugin version that supports IPv6:
- Amazon VPC CNI plugin version 1.10.0 or later is required.
- Configuration for IPv6 support is needed.
bash# Check CNI version kubectl describe daemonset aws-node --namespace kube-system | grep Image # Update CNI kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.10.0/config/master/aws-k8s-cni.yaml # Enable IPv6 kubectl set env daemonset aws-node -n kube-system ENABLE_IPV6=trueDual-stack subnets:
- Subnets must have both IPv4 and IPv6 CIDR blocks assigned.
- IPv6 routing must be configured in the route table.
bash# Assign IPv6 CIDR block to subnet aws ec2 associate-subnet-cidr-block \ --subnet-id subnet-12345 \ --ipv6-cidr-block 2600:1f16:d93:e900::/64 # Create IPv6 internet gateway aws ec2 create-egress-only-internet-gateway --vpc-id vpc-12345
Creating an EKS IPv6 Cluster:
# Create IPv6 cluster using eksctl
cat > ipv6-cluster.yaml << EOF
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ipv6-cluster
region: us-west-2
version: '1.23'
vpc:
id: vpc-12345
subnets:
private:
us-west-2a:
id: subnet-12345
us-west-2b:
id: subnet-67890
clusterEndpoints:
publicAccess: true
privateAccess: true
kubernetesNetworkConfig:
ipFamily: IPv6
managedNodeGroups:
- name: ng-1
instanceType: m5.large
desiredCapacity: 2
EOF
eksctl create cluster -f ipv6-cluster.yamlVerifying IPv6 Cluster Configuration:
# Check cluster information
aws eks describe-cluster --name ipv6-cluster --query "cluster.kubernetesNetworkConfig"
# Verify Pod IP assignment
kubectl get pods -o wide
# Verify Service IP assignment
kubectl get services -o wideCharacteristics of IPv6 Clusters:
- Pod IP Assignment:
- Pods are assigned IPv6 addresses only.
- Communication within the cluster occurs over IPv6.
- Service IP Assignment:
- ClusterIP services use IPv6 addresses.
- The default service CIDR is fd00::/108.
- DNS Configuration:
- CoreDNS is configured with IPv6 addresses.
- Service name resolution is available through AAAA records.
- External Communication:
- An Egress-Only Internet Gateway is required for internet communication.
- An IPv6-enabled load balancer is required for inbound communication.
Benefits of Using IPv6:
- Solving IP Address Exhaustion:
- Overcomes the limitations of IPv4 address space.
- Solves IP address shortage problems in large-scale clusters.
- Simplified Networking:
- No need for NAT, simplifying network configuration.
- Direct routing can improve network performance.
- Future Compatibility:
- Prepares for transition to IPv6-only environments.
- Enables leveraging new networking features and optimizations.
"IPv6-only instance types" is a non-existent concept, and most EC2 instance types support IPv6. There is no need to select special instance types to configure IPv6 in EKS.
2. What is the main benefit of configuring custom networking in an Amazon EKS cluster? - A) Separating Pod IP address range from VPC CIDR to prevent IP address conflicts - B) Reducing cluster creation time - C) Improving control plane performance - D) Encrypting node-to-node communication
Show Answer
Answer: A) Separating Pod IP address range from VPC CIDR to prevent IP address conflicts
Explanation: The main benefit of configuring custom networking in an Amazon EKS cluster is separating the Pod IP address range from the VPC CIDR to prevent IP address conflicts. This feature facilitates integration with existing network infrastructure and enables more efficient IP address management in large-scale clusters.
How Custom Networking Works:
By default, the Amazon VPC CNI plugin allocates secondary IP addresses from the node's primary network interface to provide IP addresses to Pods. In this approach, Pod IP addresses are allocated from within the VPC CIDR range. In contrast, custom networking allows you to allocate Pod IP addresses from a CIDR block separate from the VPC CIDR.
Steps to Configure Custom Networking:
Enable Custom Networking:
bash# Modify CNI plugin configuration kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=trueCreate ENIConfig Resources:
yaml# Create ENIConfig for each availability zone apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: us-west-2a spec: subnet: subnet-12345 securityGroups: - sg-12345 --- apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: us-west-2b spec: subnet: subnet-67890 securityGroups: - sg-12345Enable Availability Zone-based ENIConfig Usage:
bashkubectl set env daemonset aws-node -n kube-system ENI_CONFIG_LABEL_DEF=topology.kubernetes.io/zoneVerify Node Labels:
bashkubectl get nodes --show-labels | grep topology.kubernetes.io/zone
Benefits of Custom Networking:
- Preventing IP Address Conflicts:
- Separates Pod IP address range from VPC CIDR to prevent IP address conflicts.
- Facilitates integration with existing network infrastructure.
- Useful for peering or VPN connections between on-premises networks and VPCs.
- Flexibility in IP Address Management:
- Allows separate planning and management of Pod IP address ranges.
- Enables more efficient IP address management in large-scale clusters.
- Network Segmentation:
- Enables network segmentation by placing Pods in specific subnets.
- Network access control through security groups is possible.
- Multi-CIDR Support:
- Multiple CIDR blocks can be used to expand IP address space.
- Large-scale clusters can be built even when existing VPC CIDR is limited.
Use Cases for Custom Networking:
- Hybrid Network Environments:
- When there is connectivity between on-premises networks and AWS VPC
- When IP address space overlap must be prevented
- Large-Scale Clusters:
- When running a large number of Pods
- When VPC CIDR range is limited
- Multi-tenant Environments:
- When separate subnets are required for each tenant
- When network isolation is needed
- Regulatory Requirements:
- When regulations require placing specific workloads in specific subnets
Issues with Other Options:
- Reducing cluster creation time: Custom networking does not affect cluster creation time and may actually increase setup time due to additional configuration.
- Improving control plane performance: Custom networking only affects data plane (worker nodes and Pods) networking and does not directly impact control plane performance.
- Encrypting node-to-node communication: Custom networking only changes how IP addresses are allocated and is not related to node-to-node communication encryption. Node-to-node communication encryption must be implemented through separate security mechanisms (e.g., Calico, Cilium encryption features).
Custom networking is a powerful feature that enables more flexible configuration of EKS cluster networking, but it is complex to configure and can incur additional management overhead, so it should only be used when actually needed.
3. Which of the following is NOT a requirement for supporting Windows worker nodes in an Amazon EKS cluster? - A) At least 2 Amazon Linux-based managed node groups are required - B) VPC-CNI, kube-proxy, CoreDNS add-ons installed - C) Windows Server 2019 or later AMI - D) Cluster version 1.14 or higher
Show Answer
Answer: A) At least 2 Amazon Linux-based managed node groups are required
Explanation: To support Windows worker nodes in an Amazon EKS cluster, at least 1 (not 2 or more) Amazon Linux-based managed node group is required. This is because essential system Pods like CoreDNS must run on Linux nodes. However, it is incorrect that at least 2 Linux node groups are required.
Actual Requirements for Windows Worker Node Support in EKS:
Linux Node Group Required:
- At least 1 Linux node is required in the cluster.
- System Pods such as CoreDNS, VPC CNI plugin, and kube-proxy only run on Linux nodes.
bash# Create Linux node group eksctl create nodegroup \ --cluster my-cluster \ --name linux-ng \ --node-type m5.large \ --nodes 2VPC-CNI, kube-proxy, CoreDNS Add-ons Installed:
- These add-ons are essential components of an EKS cluster.
- Specific versions or higher may be required for Windows node support.
bash# Check add-on versions aws eks describe-addon-versions \ --addon-name vpc-cni \ --kubernetes-version 1.23 # Update add-on aws eks update-addon \ --cluster-name my-cluster \ --addon-name vpc-cni \ --addon-version v1.10.4-eksbuild.1Windows Server 2019 or Later AMI:
- Windows worker nodes must use Windows Server 2019 or later AMI.
- Using EKS-optimized Windows AMI is recommended.
bash# Create Windows node group eksctl create nodegroup \ --cluster my-cluster \ --name windows-ng \ --node-type m5.large \ --nodes 2 \ --node-ami-family WindowsServer2019FullContainerCluster Version 1.14 or Higher:
- Windows node support was officially supported starting from Kubernetes 1.14.
- Using a higher version is recommended for the latest features.
bash# Check cluster version aws eks describe-cluster --name my-cluster --query "cluster.version"
Steps to Enable Windows Support:
Enable Windows Support:
bash# Enable Windows support kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-resource-controller.yaml kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-admission-webhook.yamlCreate Windows Node Group:
bash# Create Windows node group using eksctl eksctl create nodegroup \ --cluster my-cluster \ --name windows-ng \ --node-type m5.large \ --nodes 2 \ --node-ami-family WindowsServer2019FullContainerVerify Windows Nodes:
bash# Verify nodes kubectl get nodes -o wide # Verify Windows node labels kubectl get nodes -l kubernetes.io/os=windows
Windows Container Deployment Example:
# Windows Pod deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: windows-server-iis
spec:
selector:
matchLabels:
app: windows-server-iis
tier: backend
track: stable
replicas: 2
template:
metadata:
labels:
app: windows-server-iis
tier: backend
track: stable
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: windows-server-iis
image: mcr.microsoft.com/windows/servercore:ltsc2019
ports:
- containerPort: 80
command:
- powershell.exe
- -command
- "Add-WindowsFeature Web-Server; Invoke-WebRequest -UseBasicParsing -Uri 'https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe' -OutFile 'C:\\ServiceMonitor.exe'; echo '<html><body><br/><br/><center><h1>Hello from Windows Container</h1></center></body></html>' > C:\\inetpub\\wwwroot\\default.html; C:\\ServiceMonitor.exe 'w3svc';"Windows Node Limitations:
- Networking Limitations:
- Windows nodes do not support HostPort and HostNetwork modes.
- Windows nodes do not support NodeLocal DNSCache.
- Storage Limitations:
- Windows nodes only support certain storage drivers.
- There are limitations on host path volume mounts.
- Container Runtime:
- Windows nodes only support the containerd runtime.
- Linux containers cannot run on Windows nodes.
- Feature Limitations:
- Some Kubernetes features are not supported on Windows nodes.
- There are limitations on privileged containers, process namespace sharing, etc.
To support Windows worker nodes in EKS, at least one Linux node group is required, but two or more Linux node groups are not mandatory. Therefore, "at least 2 Amazon Linux-based managed node groups are required" is not an accurate requirement.
3. Which of the following is NOT a requirement for supporting Windows worker nodes in an Amazon EKS cluster? - A) At least 2 Amazon Linux-based managed node groups are required - B) VPC-CNI, kube-proxy, CoreDNS add-ons installation - C) Windows Server 2019 or later AMI usage - D) Cluster version 1.14 or later
Show Answer
Answer: A) At least 2 Amazon Linux-based managed node groups are required
Explanation: To support Windows worker nodes in an Amazon EKS cluster, at least one (not two or more) Amazon Linux-based managed node group is required. This is because essential system pods such as CoreDNS must run on Linux nodes. However, requiring at least two Linux node groups is not accurate.
Actual Requirements for Windows Worker Node Support in EKS:
Linux Node Group Required:
- The cluster requires at least one Linux node.
- System pods such as CoreDNS, VPC CNI plugin, and kube-proxy only run on Linux nodes.
bash# Create Linux node group eksctl create nodegroup \ --cluster my-cluster \ --name linux-ng \ --node-type m5.large \ --nodes 2VPC-CNI, kube-proxy, CoreDNS Add-ons Installation:
- These add-ons are fundamental components of an EKS cluster.
- Specific versions or higher may be required for Windows node support.
bash# Check add-on versions aws eks describe-addon-versions \ --addon-name vpc-cni \ --kubernetes-version 1.23 # Update add-on aws eks update-addon \ --cluster-name my-cluster \ --addon-name vpc-cni \ --addon-version v1.10.4-eksbuild.1Windows Server 2019 or Later AMI Usage:
- Windows worker nodes must use Windows Server 2019 or later AMI.
- Using EKS-optimized Windows AMI is recommended.
bash# Create Windows node group eksctl create nodegroup \ --cluster my-cluster \ --name windows-ng \ --node-type m5.large \ --nodes 2 \ --node-ami-family WindowsServer2019FullContainerCluster Version 1.14 or Later:
- Windows node support became generally available starting with Kubernetes 1.14.
- Using a higher version is recommended for the latest features.
bash# Check cluster version aws eks describe-cluster --name my-cluster --query "cluster.version"
Steps to Enable Windows Support:
Enable Windows Support:
bash# Enable Windows support kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-resource-controller.yaml kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-admission-webhook.yamlCreate Windows Node Group:
bash# Create Windows node group using eksctl eksctl create nodegroup \ --cluster my-cluster \ --name windows-ng \ --node-type m5.large \ --nodes 2 \ --node-ami-family WindowsServer2019FullContainerVerify Windows Nodes:
bash# Verify nodes kubectl get nodes -o wide # Verify Windows node labels kubectl get nodes -l kubernetes.io/os=windows
Windows Container Deployment Example:
# Windows Pod deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: windows-server-iis
spec:
selector:
matchLabels:
app: windows-server-iis
tier: backend
track: stable
replicas: 2
template:
metadata:
labels:
app: windows-server-iis
tier: backend
track: stable
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: windows-server-iis
image: mcr.microsoft.com/windows/servercore:ltsc2019
ports:
- containerPort: 80
command:
- powershell.exe
- -command
- "Add-WindowsFeature Web-Server; Invoke-WebRequest -UseBasicParsing -Uri 'https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe' -OutFile 'C:\\ServiceMonitor.exe'; echo '<html><body><br/><br/><center><h1>Hello from Windows Container</h1></center></body></html>' > C:\\inetpub\\wwwroot\\default.html; C:\\ServiceMonitor.exe 'w3svc';"Windows Node Limitations:
- Networking Limitations:
- Windows nodes do not support HostPort and HostNetwork modes.
- Windows nodes do not support NodeLocal DNSCache.
- Storage Limitations:
- Windows nodes only support certain storage drivers.
- There are limitations on host path volume mounts.
- Container Runtime:
- Windows nodes only support the containerd runtime.
- Linux containers cannot run on Windows nodes.
- Feature Limitations:
- Some Kubernetes features are not supported on Windows nodes.
- There are limitations on privileged containers, process namespace sharing, etc.
To support Windows worker nodes in EKS, at least one Linux node group is required, but two or more Linux node groups are not mandatory. Therefore, "at least 2 Amazon Linux-based managed node groups are required" is not an accurate requirement.
- What is the most effective way to protect the Instance Metadata Service (IMDS) of node groups in an Amazon EKS cluster?
- A) Disable IMDSv1 and require IMDSv2
- B) Restrict access to 169.254.169.254 with security group rules
- C) Set restrictive permissions on the node IAM role
- D) Attach IAM roles to pod service accounts
Show Answer
Answer: A) Disable IMDSv1 and require IMDSv2
Explanation: The most effective way to protect the Instance Metadata Service (IMDS) of node groups in an Amazon EKS cluster is to disable IMDSv1 and require IMDSv2. IMDSv2 uses session-based requests to provide enhanced security features that protect against Server-Side Request Forgery (SSRF) and similar vulnerabilities.
Importance of IMDS Security:
The Instance Metadata Service provides important information about EC2 instances, including IAM role credentials. Unauthorized access to this service can lead to privilege escalation and security breaches. In Kubernetes environments, the security risk increases as pods can access the node's IMDS.
How to Configure IMDSv2:
Configure IMDSv2 Using Launch Template:
bash# Create launch template aws ec2 create-launch-template \ --launch-template-name eks-imdsv2-template \ --version-description "IMDSv2 required" \ --launch-template-data '{ "MetadataOptions": { "HttpTokens": "required", "HttpPutResponseHopLimit": 1, "HttpEndpoint": "enabled" } }' # Create node group using launch template eksctl create nodegroup \ --cluster my-cluster \ --name ng-imdsv2 \ --node-type m5.large \ --nodes 3 \ --launch-template-name eks-imdsv2-template \ --launch-template-version 1Configure IMDSv2 Using eksctl Configuration File:
yamlapiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster region: us-west-2 managedNodeGroups: - name: ng-imdsv2 instanceType: m5.large minSize: 2 maxSize: 5 disableIMDSv1: true metadataOptions: httpTokens: required httpPutResponseHopLimit: 1Modify Existing Node Groups: To change the IMDS settings of existing node groups, you need to create a new node group and migrate workloads. The IMDS settings of existing EC2 instances can be modified as follows:
bashaws ec2 modify-instance-metadata-options \ --instance-id i-1234567890abcdef0 \ --http-tokens required \ --http-put-response-hop-limit 1 \ --http-endpoint enabled
Security Benefits of IMDSv2:
- Session-Based Authentication:
- IMDSv2 uses tokens generated through PUT requests to authenticate subsequent requests.
- These tokens are valid for a limited time only.
- SSRF Attack Prevention:
- Prevents metadata access through Server-Side Request Forgery (SSRF) vulnerabilities.
- Metadata cannot be accessed without a token.
- Hop Limit Setting:
- Setting the HTTP PUT response hop limit prevents metadata requests from being redirected outside the instance.
- The default value is 1, ensuring requests are only processed within the instance.
Additional IMDS Security Measures:
Completely Disable IMDS: If IMDS is not needed for certain workloads, it can be completely disabled:
yamlmetadataOptions: httpEndpoint: disabledBlock Pod Access to IMDS: If pods are not using host networking, you can add iptables rules to block IMDS access:
bashiptables -t nat -A PREROUTING -d 169.254.169.254/32 -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:1Use IRSA: Use IAM Roles for Service Accounts (IRSA) to provide pods with the necessary AWS permissions and eliminate dependency on node IMDS.
Issues with Other Options:
- Restrict access to 169.254.169.254 with security group rules: Security groups control traffic coming from outside the instance, but IMDS is accessed from inside the instance, so it cannot be restricted with security groups.
- Set restrictive permissions on the node IAM role: This is a good security practice, but it does not strengthen the security of IMDS itself. If an attacker can access IMDS, even limited permissions can be exploited.
- Attach IAM roles to pod service accounts: IRSA is a good way to ensure pods don't depend on node IMDS, but it does not directly strengthen the security of node IMDS itself.
Disabling IMDSv1 and requiring IMDSv2 is the most effective way to protect the metadata service of EKS nodes. This is an AWS security best practice and is especially important in multi-tenant Kubernetes environments.
- Which of the following is NOT a primary purpose of customizing bootstrap scripts when creating node groups in an Amazon EKS cluster?
- A) Modifying cluster control plane components
- B) Installing additional software
- C) Adjusting kernel parameters
- D) Setting node labels and taints
Show Answer
Answer: A) Modifying cluster control plane components
Explanation: The primary purpose of customizing bootstrap scripts when creating node groups in an Amazon EKS cluster is NOT to modify cluster control plane components. EKS is a managed service where the control plane is managed by AWS and cannot be directly modified by users. Bootstrap scripts can only modify worker node configurations.
Actual Use Cases for Bootstrap Scripts:
Installing Additional Software:
- Monitoring agents (CloudWatch Agent, Prometheus Node Exporter, etc.)
- Logging tools (Fluentd, Fluent Bit, etc.)
- Security tools (Falco, Sysdig, etc.)
- Performance optimization tools
bash#!/bin/bash # Install CloudWatch agent wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm rpm -U amazon-cloudwatch-agent.rpm # Create configuration file cat > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json << 'EOF' { "metrics": { "metrics_collected": { "mem": { "measurement": ["mem_used_percent"] }, "swap": { "measurement": ["swap_used_percent"] } } } } EOF # Start agent /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -sAdjusting Kernel Parameters:
- Network setting optimization
- Memory management settings
- File system and I/O settings
bash#!/bin/bash # Adjust kernel parameters cat > /etc/sysctl.d/99-kubernetes.conf << EOF net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_max_syn_backlog = 40000 net.core.somaxconn = 40000 net.core.netdev_max_backlog = 40000 vm.max_map_count = 262144 EOF # Apply changes sysctl --systemSetting Node Labels and Taints:
- Setting node role labels
- Setting hardware characteristic labels
- Setting taints for specific workloads
bash#!/bin/bash # Execute EKS bootstrap script /etc/eks/bootstrap.sh my-cluster \ --kubelet-extra-args '--node-labels=node.kubernetes.io/role=worker,environment=prod,node-type=compute --register-with-taints=dedicated=compute:NoSchedule'Disk and File System Configuration:
- Mounting additional volumes
- File system optimization
- Temporary storage configuration
bash#!/bin/bash # Format and mount additional EBS volume mkfs -t xfs /dev/nvme1n1 mkdir -p /data mount /dev/nvme1n1 /data echo "/dev/nvme1n1 /data xfs defaults 0 0" >> /etc/fstabSecurity Configuration:
- Setting firewall rules
- Security hardening settings
- Log audit configuration
bash#!/bin/bash # Set firewall rules iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP # Security hardening settings sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config systemctl restart sshd
How to Implement Bootstrap Scripts:
User Data Script Using Launch Template:
bash# Create launch template aws ec2 create-launch-template \ --launch-template-name eks-custom-bootstrap \ --version-description "Custom bootstrap script" \ --launch-template-data '{ "UserData": "BASE64_ENCODED_USER_DATA_SCRIPT" }' # Create node group using launch template eksctl create nodegroup \ --cluster my-cluster \ --name custom-ng \ --node-type m5.large \ --nodes 3 \ --launch-template-name eks-custom-bootstrap \ --launch-template-version 1User Data Script Using eksctl Configuration File:
yamlapiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster region: us-west-2 managedNodeGroups: - name: custom-ng instanceType: m5.large minSize: 2 maxSize: 5 preBootstrapCommands: - "echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.d/99-kubernetes.conf" - "sysctl --system" kubeletExtraArgs: node-labels: "environment=prod,node-type=compute"
Cluster Control Plane Components:
The control plane components of an EKS cluster are managed by AWS and cannot be modified through bootstrap scripts:
- API Server
- Controller Manager
- Scheduler
- etcd
- CoreDNS
To modify these components, you must configure them at the cluster level through AWS-provided APIs. For example, control plane logging can be configured as follows:
aws eks update-cluster-config \
--name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'The bootstrap script can only modify worker node configurations and cannot modify cluster control plane components. Therefore, "modifying cluster control plane components" is not a primary purpose of the bootstrap script.