Sari la conținutul principal

Cluster Kubernetes în AWS

Pentru a face deployment unui cluster de Kubernetes în AWS avem 2 opțiuni.

Facem deploy la mai multe mașini virtuale și instalăm și configurăm un cluster de mână. Folosim serviciul AWS special conceput pentru clusters de Kubernetes, AWS EKS Cluster În cazul acestui laborator, o să facem deployment la un cluster folosind EKS.

Pentru a urma best practices recomandate de hashicorp, o să spargem codul în mai multe fișiere.

Fișierul variables.tf o sa conțină o simplă variabilă în care definim zona în care vrem să facem deployment:

variable "region" {
description = "AWS region"
type = string
default = "us-west-2"
}

Mai departe avem nevoie de un VPC, deci vom crea un nou fisier vpc.tf. Mai multe despre ce este un VPC: aici.

module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.14.2"

name = "cc-vpc"

cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)

private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]

enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true

public_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/elb" = 1
}

private_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/internal-elb" = 1
}
}

Mai multe detalii despre modulul de Terraform pentru VPC: aici.

În continuare avem nevoie de 2 security groups, pe care o să le folosească cluster-ul nostru. Așadar creăm un nou fișier cu numele securityGroups.tf cu următorul conținut:

resource "aws_security_group" "node_group_one" {
name_prefix = "node_group_one"
vpc_id = module.vpc.vpc_id

ingress {
from_port = 22
to_port = 22
protocol = "tcp"

cidr_blocks = [
"10.0.0.0/8",
]
}
}

resource "aws_security_group" "node_group_two" {
name_prefix = "node_group_two"
vpc_id = module.vpc.vpc_id

ingress {
from_port = 22
to_port = 22
protocol = "tcp"

cidr_blocks = [
"192.168.0.0/16",
]
}
}

Ne putem gândi la un security group ca la un firewall. Mai multe detalii în documentație. Documentația unui security group de AWS în Terraform: aici.

Până acum am definit doar componentele de care o să ne folosim în momentul în care configurăm cluster-ul nostru. Pentru a face asta, avem un nou fișier cluster.tf cu următoarea configurație:

module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "18.26.6"

cluster_name = local.cluster_name
cluster_version = "1.22"

vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets

eks_managed_node_group_defaults = {
ami_type = "AL2_x86_64"

attach_cluster_primary_security_group = true

# Disabling and using externally provided security groups
create_security_group = false
}

eks_managed_node_groups = {
one = {
name = "node-group-1"

instance_types = ["t3.small"]

min_size = 1
max_size = 3
desired_size = 2

pre_bootstrap_user_data = <<-EOT
echo 'foo bar'
EOT

vpc_security_group_ids = [
aws_security_group.node_group_one.id
]
}

two = {
name = "node-group-2"

instance_types = ["t3.medium"]

min_size = 1
max_size = 2
desired_size = 1

pre_bootstrap_user_data = <<-EOT
echo 'foo bar'
EOT

vpc_security_group_ids = [
aws_security_group.node_group_two.id
]
}
}
}

Mai avem doar de creat un fișier main.tf cu următoarea configurație:

provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
}

provider "aws" {
region = var.region
}

data "aws_availability_zones" "available" {}

locals {
cluster_name = "cc-eks-${random_string.suffix.result}"
}

resource "random_string" "suffix" {
length = 8
special = false
}

Pentru a afișa câteva informații legate de infrastructura noastră avem nevoie de câteva outputs. Așa cum am învățat data trecută, facem un fișier separat în care definim acest outputs:

output "cluster_id" {
description = "EKS cluster ID"
value = module.eks.cluster_id
}

output "cluster_endpoint" {
description = "Endpoint for EKS control plane"
value = module.eks.cluster_endpoint
}

output "cluster_security_group_id" {
description = "Security group ids attached to the cluster control plane"
value = module.eks.cluster_security_group_id
}

output "region" {
description = "AWS region"
value = var.region
}

output "cluster_name" {
description = "Kubernetes Cluster Name"
value = local.cluster_name
}

Rulăm comenzile obișnuite pentru a crea infrastructura. Observați ca sunt foarte multe resurse care urmează să se construiască.

In cazul in care ați realizat ca lipsește ceva (nu am definit niciunde ce versiuni ale provider-ilor vrem să folosim), best practices recomandă să avem un fișier numit terraform.tf care să conțină această configurație:

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.15.0"
}

random = {
source = "hashicorp/random"
version = "~> 3.1.0"
}

tls = {
source = "hashicorp/tls"
version = "~> 3.4.0"
}

cloudinit = {
source = "hashicorp/cloudinit"
version = "~> 2.2.0"
}

kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.12.1"
}
}
}

Asteptați ca planul să se termine de rulat și verificați infrastructura creată în AWS (o să dureze în jur de 15-20 minute). Apoi, pentru a ne conecta la cluster-ul nostru proaspăt creat de Kubernetes, folosim următoarea comandă:

aws eks --region $(terraform output -raw region) update-kubeconfig \
--name $(terraform output -raw cluster_name)

Verificați conexiunea cu următoarea comandă: kubectl cluster-info

În acest moment avem un cluster configurat în AWS EKS și suntem conectați la el. Orice comandă de kubectl rulată o să fie executată pe cluster-ul nostru.