├── README.md ├── ansible.cfg ├── k8s ├── k8s.pub ├── keypair.tf ├── main.tf ├── master.sh ├── outputs.tf ├── playbook.yml ├── provider.tf ├── security_groups.tf ├── variables.tf └── worker.sh /README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes v1.28 on AWS using Kubeadm and Terraform 2 | 3 | ## Installing tools 4 | 5 | ### Installing Terraform 6 | ``` 7 | sudo yum install -y yum-utils 8 | sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo 9 | sudo yum -y install terraform 10 | ``` 11 | ### Installing Ansible 12 | ``` 13 | pip3 install ansible 14 | ``` 15 | ``` 16 | $ sudo su 17 | # whereis ansible 18 | ansible: /usr/local/bin/ansible 19 | ``` 20 | Updating path 21 | ``` 22 | echo "export PATH=$PATH:/usr/local/bin/" >> ~/.bashrc 23 | source ~/.bashrc 24 | ``` 25 | ``` 26 | # ansible --version 27 | # ansible-playbook --version 28 | ``` 29 | ### Installing Git 30 | ``` 31 | yum install git -y 32 | ``` 33 | 34 | ## Configure AWS CLI 35 | ### Create IAM user and add credentials 36 | ``` 37 | aws configure 38 | ``` 39 | 40 | ## References 41 | - https://github.com/kunchalavikram1427/YouTube_Series/blob/main/Kubernetes/ClusterSetup/Kubernetes_v1.28_on_aws_with_containerd.md 42 | - https://github.com/kunchalavikram1427/ansible-terraform-integration 43 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | remote_user = ubuntu 3 | private_key_file = ./k8s 4 | host_key_checking = False -------------------------------------------------------------------------------- /k8s: -------------------------------------------------------------------------------- 1 | -----BEGIN OPENSSH PRIVATE KEY----- 2 | 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 38 | -----END OPENSSH PRIVATE KEY----- 39 | -------------------------------------------------------------------------------- /k8s.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDwoELN4zC2bjBp55tBJ0EhrPjypaAtOP6FGbwd6CLfLgL3kUUsZkMedbmyiOxozW+hb1OqCJ69rEOILdxO4q8Um7ZjGb6AjsxWlLxyXsqrhuLuh9N/s+YTaFQgV92jUmEuTaHXfkd2FGquiEXujSAlt4dXjnGNGBAZXDDlqa4m0/Rn39mMk4FR7WFSmLHg8Wp0KoqCeR1TnGhWuQ4zF0uXZeGljh23qbWir/yLlGs62/M9pYJMxO7rc3nWBYqFQp/Tnc8mI45h/CgdvrL8dLQINWHtVUYWnqivIdgYU4MN0DjVNzCSKdxrl9pSiAWZLUAzHYwc8Uvg2Wz7ZdLdxlyobPKNyUikvNzKk1vKBTz8t+XxSq0SinaD91aiSq3Kf2xltV7xhV5gk7vuu/BrW0cVs3phN0cwgG3Hzw+upoHTLlty1dLjXgoyiw842ysgQ14gVNUNVoV/YTYHAhI2ZUV4S9sH2YD1haNUgKVyzZuNVC0VCTT9f3TKULZSfayZO0= kunch@DESKTOP-ML06FR4 2 | -------------------------------------------------------------------------------- /keypair.tf: -------------------------------------------------------------------------------- 1 | resource "aws_key_pair" "k8s" { 2 | key_name = "k8s" 3 | public_key = file("k8s.pub") 4 | } -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | # Launch master node 2 | resource "aws_instance" "k8s_master" { 3 | ami = var.ami["master"] 4 | instance_type = var.instance_type["master"] 5 | tags = { 6 | Name = "k8s-master" 7 | } 8 | key_name = aws_key_pair.k8s.key_name 9 | security_groups = ["k8s_master_sg"] 10 | 11 | connection { 12 | type = "ssh" 13 | user = "ubuntu" 14 | private_key = file("k8s") 15 | host = self.public_ip 16 | } 17 | provisioner "file" { 18 | source = "./master.sh" 19 | destination = "/home/ubuntu/master.sh" 20 | } 21 | provisioner "remote-exec" { 22 | inline = [ 23 | "chmod +x /home/ubuntu/master.sh", 24 | "sudo sh /home/ubuntu/master.sh k8s-master" 25 | ] 26 | } 27 | provisioner "local-exec" { 28 | command = "ansible-playbook -i '${self.public_ip},' playbook.yml" 29 | } 30 | } 31 | 32 | # Launch worker nodes 33 | resource "aws_instance" "k8s_worker" { 34 | count = var.worker_instance_count 35 | ami = var.ami["worker"] 36 | instance_type = var.instance_type["worker"] 37 | tags = { 38 | Name = "k8s-worker-${count.index}" 39 | } 40 | key_name = aws_key_pair.k8s.key_name 41 | security_groups = ["k8s_worker_sg"] 42 | depends_on = [aws_instance.k8s_master] 43 | connection { 44 | type = "ssh" 45 | user = "ubuntu" 46 | private_key = file("k8s") 47 | host = self.public_ip 48 | } 49 | provisioner "file" { 50 | source = "./worker.sh" 51 | destination = "/home/ubuntu/worker.sh" 52 | } 53 | provisioner "file" { 54 | source = "./join-command.sh" 55 | destination = "/home/ubuntu/join-command.sh" 56 | } 57 | provisioner "remote-exec" { 58 | inline = [ 59 | "chmod +x /home/ubuntu/worker.sh", 60 | "sudo sh /home/ubuntu/worker.sh k8s-worker-${count.index}", 61 | "sudo sh /home/ubuntu/join-command.sh" 62 | ] 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Set hostname 5 | echo "-------------Setting hostname-------------" 6 | hostnamectl set-hostname $1 7 | 8 | # Disable swap 9 | echo "-------------Disabling swap-------------" 10 | swapoff -a 11 | sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab 12 | 13 | # Install Containerd 14 | echo "-------------Installing Containerd-------------" 15 | wget https://github.com/containerd/containerd/releases/download/v1.7.4/containerd-1.7.4-linux-amd64.tar.gz 16 | tar Cxzvf /usr/local containerd-1.7.4-linux-amd64.tar.gz 17 | wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service 18 | mkdir -p /usr/local/lib/systemd/system 19 | mv containerd.service /usr/local/lib/systemd/system/containerd.service 20 | systemctl daemon-reload 21 | systemctl enable --now containerd 22 | 23 | # Install Runc 24 | echo "-------------Installing Runc-------------" 25 | wget https://github.com/opencontainers/runc/releases/download/v1.1.9/runc.amd64 26 | install -m 755 runc.amd64 /usr/local/sbin/runc 27 | 28 | # Install CNI 29 | echo "-------------Installing CNI-------------" 30 | wget https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz 31 | mkdir -p /opt/cni/bin 32 | tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.2.0.tgz 33 | 34 | # Install CRICTL 35 | echo "-------------Installing CRICTL-------------" 36 | VERSION="v1.28.0" # check latest version in /releases page 37 | wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz 38 | tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin 39 | rm -f crictl-$VERSION-linux-amd64.tar.gz 40 | 41 | cat < ./join-command.sh 104 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "master" { 2 | value = aws_instance.k8s_master.public_ip 3 | } 4 | 5 | output "workers" { 6 | value = aws_instance.k8s_worker[*].public_ip 7 | } -------------------------------------------------------------------------------- /playbook.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | name: fetch join token file 3 | gather_facts: false 4 | become: yes 5 | tasks: 6 | - name: fetch join token file 7 | ansible.builtin.fetch: 8 | src: /home/ubuntu/join-command.sh 9 | dest: ./join-command.sh 10 | flat: yes 11 | validate_checksum: false 12 | -------------------------------------------------------------------------------- /provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "5.21.0" 6 | } 7 | } 8 | } 9 | 10 | provider "aws" { 11 | region = var.region 12 | profile = "default" 13 | } -------------------------------------------------------------------------------- /security_groups.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "k8s_master" { 2 | name = "k8s_master_sg" 3 | description = "k8s_master Security Group" 4 | 5 | ingress { 6 | description = "SSH" 7 | from_port = 22 8 | to_port = 22 9 | protocol = "tcp" 10 | cidr_blocks = ["0.0.0.0/0"] 11 | ipv6_cidr_blocks = ["::/0"] 12 | } 13 | 14 | ingress { 15 | description = "API Server" 16 | from_port = 6443 17 | to_port = 6443 18 | protocol = "tcp" 19 | cidr_blocks = ["0.0.0.0/0"] 20 | ipv6_cidr_blocks = ["::/0"] 21 | } 22 | 23 | ingress { 24 | description = "ETCD" 25 | from_port = 2379 26 | to_port = 2380 27 | protocol = "tcp" 28 | cidr_blocks = ["0.0.0.0/0"] 29 | ipv6_cidr_blocks = ["::/0"] 30 | } 31 | 32 | ingress { 33 | description = "Weavenet TCP" 34 | from_port = 6783 35 | to_port = 6783 36 | protocol = "tcp" 37 | cidr_blocks = ["0.0.0.0/0"] 38 | ipv6_cidr_blocks = ["::/0"] 39 | } 40 | 41 | ingress { 42 | description = "Weavenet TCP" 43 | from_port = 6784 44 | to_port = 6784 45 | protocol = "udp" 46 | cidr_blocks = ["0.0.0.0/0"] 47 | ipv6_cidr_blocks = ["::/0"] 48 | } 49 | 50 | ingress { 51 | description = "Kubelet API, Kube-scheduler, Kube-controller-manager, Read-Only Kubelet API, Kubelet health" 52 | from_port = 10248 53 | to_port = 10260 54 | protocol = "tcp" 55 | cidr_blocks = ["0.0.0.0/0"] 56 | ipv6_cidr_blocks = ["::/0"] 57 | } 58 | 59 | ingress { 60 | description = "NodePort Services" 61 | from_port = 30000 62 | to_port = 32767 63 | protocol = "tcp" 64 | cidr_blocks = ["0.0.0.0/0"] 65 | ipv6_cidr_blocks = ["::/0"] 66 | } 67 | 68 | egress { 69 | from_port = 0 70 | to_port = 0 71 | protocol = "-1" 72 | cidr_blocks = ["0.0.0.0/0"] 73 | ipv6_cidr_blocks = ["::/0"] 74 | } 75 | 76 | tags = { 77 | Name = "k8s_master_sg" 78 | } 79 | } 80 | 81 | resource "aws_security_group" "k8s_worker" { 82 | name = "k8s_worker_sg" 83 | description = "k8s_worker Security Group" 84 | 85 | ingress { 86 | description = "SSH" 87 | from_port = 22 88 | to_port = 22 89 | protocol = "tcp" 90 | cidr_blocks = ["0.0.0.0/0"] 91 | ipv6_cidr_blocks = ["::/0"] 92 | } 93 | 94 | ingress { 95 | description = "Weavenet TCP" 96 | from_port = 6783 97 | to_port = 6783 98 | protocol = "tcp" 99 | cidr_blocks = ["0.0.0.0/0"] 100 | ipv6_cidr_blocks = ["::/0"] 101 | } 102 | 103 | ingress { 104 | description = "Weavenet TCP" 105 | from_port = 6784 106 | to_port = 6784 107 | protocol = "udp" 108 | cidr_blocks = ["0.0.0.0/0"] 109 | ipv6_cidr_blocks = ["::/0"] 110 | } 111 | 112 | ingress { 113 | description = "Kubelet API, Kube-scheduler, Kube-controller-manager, Read-Only Kubelet API, Kubelet health" 114 | from_port = 10248 115 | to_port = 10260 116 | protocol = "tcp" 117 | cidr_blocks = ["0.0.0.0/0"] 118 | ipv6_cidr_blocks = ["::/0"] 119 | } 120 | 121 | ingress { 122 | description = "NodePort Services" 123 | from_port = 30000 124 | to_port = 32767 125 | protocol = "tcp" 126 | cidr_blocks = ["0.0.0.0/0"] 127 | ipv6_cidr_blocks = ["::/0"] 128 | } 129 | 130 | egress { 131 | from_port = 0 132 | to_port = 0 133 | protocol = "-1" 134 | cidr_blocks = ["0.0.0.0/0"] 135 | ipv6_cidr_blocks = ["::/0"] 136 | } 137 | 138 | tags = { 139 | Name = "k8s_worker_sg" 140 | } 141 | } 142 | 143 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | default = "us-east-1" 3 | } 4 | 5 | variable "ami" { 6 | type = map(string) 7 | default = { 8 | master = "ami-0261755bbcb8c4a84" 9 | worker = "ami-0261755bbcb8c4a84" 10 | } 11 | } 12 | 13 | variable "instance_type" { 14 | type = map(string) 15 | default = { 16 | master = "t2.medium" 17 | worker = "t2.micro" 18 | } 19 | } 20 | 21 | variable "worker_instance_count" { 22 | type = number 23 | default = 2 24 | } -------------------------------------------------------------------------------- /worker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Set hostname 5 | echo "-------------Setting hostname-------------" 6 | hostnamectl set-hostname $1 7 | 8 | # Disable swap 9 | echo "-------------Disabling swap-------------" 10 | swapoff -a 11 | sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab 12 | 13 | # Install Containerd 14 | echo "-------------Installing Containerd-------------" 15 | wget https://github.com/containerd/containerd/releases/download/v1.7.4/containerd-1.7.4-linux-amd64.tar.gz 16 | tar Cxzvf /usr/local containerd-1.7.4-linux-amd64.tar.gz 17 | wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service 18 | mkdir -p /usr/local/lib/systemd/system 19 | mv containerd.service /usr/local/lib/systemd/system/containerd.service 20 | systemctl daemon-reload 21 | systemctl enable --now containerd 22 | 23 | # Install Runc 24 | echo "-------------Installing Runc-------------" 25 | wget https://github.com/opencontainers/runc/releases/download/v1.1.9/runc.amd64 26 | install -m 755 runc.amd64 /usr/local/sbin/runc 27 | 28 | # Install CNI 29 | echo "-------------Installing CNI-------------" 30 | wget https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz 31 | mkdir -p /opt/cni/bin 32 | tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.2.0.tgz 33 | 34 | # Install CRICTL 35 | echo "-------------Installing CRICTL-------------" 36 | VERSION="v1.28.0" # check latest version in /releases page 37 | wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz 38 | sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin 39 | rm -f crictl-$VERSION-linux-amd64.tar.gz 40 | 41 | cat <