The Theory
To make an Amazon Elastic Kubernetes Service (EKS) cluster private and allow nodes to join through a node group, you need to follow a few steps. By default, EKS creates a public cluster, but you can configure it to make it private for enhanced security. Here’s an overview of the process:
- Create a VPC: Start by creating a Virtual Private Cloud (VPC) in your AWS account if you haven’t already. This VPC will be used to host your private EKS cluster.
- Create private subnets: Within the VPC, create one or more private subnets. These subnets will provide the network isolation required for a private cluster. Make sure the subnets have no direct internet access and that their route tables do not have an internet gateway attached.
- Create security groups: Create security groups to define the inbound and outbound traffic rules for your EKS cluster and nodes. These security groups should allow communication between the control plane and the worker nodes, as well as any other necessary network traffic.
- Create a NAT gateway: Since the private subnets don’t have direct internet access, you need to set up a Network Address Translation (NAT) gateway in a public subnet to enable outbound internet connectivity for resources in the private subnets.
- Configure VPC endpoints: Create VPC endpoints for EKS and EC2 to allow private communication between your EKS cluster control plane and the worker nodes. These endpoints will ensure that the control plane and nodes can communicate without requiring access to the public internet.
- Create a private EKS cluster: Now, create a private EKS cluster using the AWS Management Console, AWS CLI, or AWS SDKs. During the cluster creation, specify the private subnets, security groups, and VPC endpoints you created earlier. This will ensure that the cluster is deployed within the private subnets and can communicate with the nodes via the VPC endpoints.
- Create a node group: Once the cluster is created, you can proceed to create a node group. When creating the node group, specify the private subnets and security groups that you set up earlier. The node group will be deployed in the private subnets and join the private EKS cluster.
Following these steps will result in a private EKS cluster where the control plane and worker nodes communicate privately through the VPC endpoints. The private nature of the cluster enhances security by reducing exposure to the public internet.
Note that these steps provide a high-level overview of the process, and there may be additional considerations or customizations based on your specific requirements. For detailed instructions and the most up-to-date information, it’s recommended to refer to the official AWS EKS documentation.
How to do this in Terraform
To create a private Amazon EKS cluster and allow nodes to join through a node group using Terraform, you can follow the steps outlined below:
- Set up the necessary Terraform files: Create a new directory for your Terraform configuration and create the main.tf file inside it.
- Configure the AWS provider: In the main.tf file, configure the AWS provider to define your AWS access credentials and the desired region:
provider "aws" {
region = "your_region"
}
- Create a VPC: Define a VPC resource to create the Virtual Private Cloud:
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
}
- Create private subnets: Define private subnets within the VPC to host your EKS cluster:
resource "aws_subnet" "private_subnet" {
count = 2
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.${count.index}.0/24"
}
- Create security groups: Define security groups to allow inbound and outbound traffic for the EKS cluster:
resource "aws_security_group" "eks_cluster_sg" {
vpc_id = aws_vpc.my_vpc.id
# Define inbound and outbound rules as per your requirements
# Example:
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
- Create a NAT gateway: Configure a NAT gateway to provide outbound internet access to resources in the private subnets:
resource "aws_eip" "nat_eip" {
vpc = true
}
resource "aws_nat_gateway" "nat_gateway" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.private_subnet[0].id
}
# Create a route table entry for the NAT gateway
resource "aws_route" "private_subnet_nat_route" {
route_table_id = aws_subnet.private_subnet[0].route_table_id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_gateway.id
}
- Configure VPC endpoints: Create VPC endpoints for EKS and EC2 to enable private communication:
resource "aws_vpc_endpoint" "eks_endpoint" {
vpc_id = aws_vpc.my_vpc.id
service_name = "com.amazonaws.${var.region}.eks"
}
resource "aws_vpc_endpoint" "ec2_endpoint" {
vpc_id = aws_vpc.my_vpc.id
service_name = "com.amazonaws.${var.region}.ec2"
}
- Create a private EKS cluster: Define the EKS cluster resource with the appropriate settings:
resource "aws_eks_cluster" "my_eks_cluster" {
name = "my-cluster"
role_arn = aws_iam_role.my_eks_role.arn
vpc_config {
subnet_ids = aws_subnet.private_subnet[*].id
security_group_ids = [aws_security_group.eks_cluster_sg.id]
endpoint_private_access = true
endpoint_public_access = false
}
depends_on = [
aws_vpc_endpoint.eks_endpoint,
aws_vpc_endpoint.ec2_endpoint
]
}
- Create a node group: Define the EKS node group resource to join the private EKS cluster:
resource "aws_eks_node_group" "my_eks_nodegroup" {
cluster_name = aws_eks_cluster.my_eks_cluster.name
node_group_name = "my-nodegroup"
node_group_config {
instance_type = "your_instance_type"
desired_size = 1
min_size = 1
max_size = 1
subnet_ids = aws_subnet.private_subnet[*].id
ami_type = "AL2_x86_64"
}
}
- Apply the Terraform configuration: Initialize the Terraform working directory and apply the configuration:
terraform init
terraform apply
This configuration will create a private VPC, subnets, security groups, NAT gateway, VPC endpoints, EKS cluster, and a node group that joins the private cluster.
Make sure to customize the configuration according to your specific requirements, such as VPC CIDR blocks, security group rules, EKS cluster name, node group instance type, etc.
Note: This is a simplified example, and there may be additional resources or configuration options you need to consider based on your specific needs. It’s recommended to refer to the Terraform AWS provider documentation for detailed information on each resource and its attributes.
How to do this in CloudFormation
To create a private Amazon EKS cluster and allow nodes to join through a node group using AWS CloudFormation, you can use AWS CloudFormation templates to define the infrastructure as code. Here’s an outline of the steps to accomplish this:
- Create an AWS CloudFormation template: Create a new CloudFormation template in YAML or JSON format. This template will define the resources required for your private EKS cluster.
- Define the VPC and subnets: Specify the VPC and private subnets where your EKS cluster will reside:
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: 10.0.0.0/24
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: 10.0.1.0/24
- Create security groups: Define the security groups to control inbound and outbound traffic for your EKS cluster:
Resources:
EKSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EKS security group
VpcId: !Ref MyVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: "-1"
FromPort: 0
ToPort: 0
CidrIp: 0.0.0.0/0
- Create a NAT gateway: Set up a NAT gateway to enable outbound internet access for the private subnets:
Resources:
MyEIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
MyNATGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt MyEIP.AllocationId
SubnetId: !Ref PrivateSubnet1
PrivateSubnet1RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
PrivateSubnet1Route:
Type: AWS::EC2::Route
DependsOn: MyNATGateway
Properties:
RouteTableId: !Ref PrivateSubnet1RouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref MyNATGateway
PrivateSubnet1Association:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateSubnet1RouteTable
- Configure VPC endpoints: Create VPC endpoints for EKS and EC2 to enable private communication:
Resources:
EKSEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref MyVPC
ServiceName: com.amazonaws.<region>.eks
EC2Endpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref MyVPC
ServiceName: com.amazonaws.<region>.ec2
- Create a private EKS cluster: Define the EKS cluster resource with the appropriate settings:
Resources:
MyEKSCluster:
Type: AWS::EKS::Cluster
Properties:
Name: my-cluster
ResourcesVpcConfig:
SecurityGroupIds:
- !Ref EKSSecurityGroup
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
Version: "1.21"
RoleArn: arn:aws:iam::123456789012:role/MyEKSClusterRole
KubernetesNetworkConfig:
ServiceIpv4Cidr: "10.100.0.0/16"
- Create a node group: Define the EKS node group resource to join the private EKS cluster:
Resources:
MyEKSNodeGroup:
Type: AWS::EKS::Nodegroup
Properties:
ClusterName: !Ref MyEKSCluster
NodegroupName: my-nodegroup
ScalingConfig:
DesiredSize: 1
MinSize: 1
MaxSize: 3
Subnets:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
InstanceTypes:
- t3.medium
RemoteAccess:
Ec2SshKey: my-key-pair
- Deploy the CloudFormation stack: Use the AWS Management Console, AWS CLI, or AWS SDKs to deploy the CloudFormation stack with your template.
Ensure that you customize the configuration based on your specific requirements, such as VPC CIDR blocks, security group rules, EKS cluster name, node group instance type, etc.
Please note that this is a simplified example, and additional considerations and customization may be required based on your specific needs. For more detailed information on each resource and its properties, consult the AWS CloudFormation documentation.