In this post I cover how I create a cluster to compile the linux kernel. Recently I needed to compile the linux kernel for my personal PC and it was really slow with only 2 cores, 4 threads. it ocurred to me, I didn’t need a new computer, perhaps I could compile the kernel in aws using ec2 instances. However if I had only one EC2 instance it will be the same case, unless I chose a really big instance type, but I could create a cluster of cheaper machines and have them running to compile the linux kernel, then I could copy the generated files over ssh to my current laptop and destroy all the infrastructure.
The first step is to create an ubuntu image with packer, this image will be the one used for all the nodes, and it will have all the tools needed to compile a linux kernel.
main_image.json
{
"variables" : {
"provs" : "provisioners"
},
"builders" : [
{
"type" : "amazon-ebs",
"profile" : "your-profile",
"region": "us-east-1",
"source_ami_filter": {
"filters" : {
"virtualization-type":"hvm",
"name":"ubuntu/images/*ubuntu-bionic-18.04-amd64-server-*",
"root-device-type" : "ebs"
},
"owners": ["099720109477"],
"most_recent": true
},
"instance_type": "t2.micro",
"ami_name": "vault_image",
"ssh_username": "ubuntu",
"tags":{"Name":"compiler-image"}
}],
"provisioners" : [
{
"type" : "shell",
"inline": [
"sleep 30",
"sudo apt update",
"sudo apt install -y ansible",
"sudo apt install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev distcc"
]
}]
}
The packages needed to perform this operation are build-essential and distcc, ansible is needed in order to run an ad-hoc command to start the distccd daemon
To actually create the infrastructure I used terraform, the following code is just the main file, the rest of the code can be seen at github.com/mental12345/aws_compilation_cluster
main.tf
provider "aws" {
profile = "your-profile"
region = var.region
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_ipv6 = false
enable_nat_gateway = true
single_nat_gateway = true
vpc_tags = {
Name = "cluster-vpc"
}
}
module "ec2_farm"{
source = "./modules/comp_farm"
vpc_id = module.vpc.vpc_id
private_subnets = module.vpc.private_subnets
ins_type = var.ins_type
ami = var.ami
env = var.env
ec2number = 2
ec2min = 1
ec2max = 3
ssh_key = "main.pub"
}
module "ec2_main" {
source = "./modules/ec2_main"
vpc_id = module.vpc.vpc_id
public_subnet = module.vpc.public_subnets[0]
ins_type = var.ins_type
ami = var.ami
env = var.env
ssh_key = "main.pub"
}
There are 3 modules, the first is to create a vpc on which all of the operations are going to be performed, the ec2_farm module creates the instances in a private subnet with the ports 22 and 3632 open. And finally the module ec2_main creates only a ec2 instance with the same ports.
Once finished the creation of the infrastructure, ansible will help running the following commands in the node instances distccd –daemon –allow main_ip main_ip being the IP of the main ec2 where I’m performing all of the operations. Also on the main ec2 export the following variable, export DISTCC_HOSTS=‘localhost IP1 IP2 IP3 IPn’ where IP1 and IP2 are the private IPs of the ec2 isntances in the cluster.
In order to actually compile the linux kernel, make -j4 CC=“distcc gcc”
Testing
1 instance t2.micro time: 21m48.775s
3 instance t2.micro time: 10m22.580s