JUST WRITE

명령어 한 번에 Kubernetes 설치하기(2) - AWS ENI를 이용한 설치 본문

MLOps/Kubernetes

명령어 한 번에 Kubernetes 설치하기(2) - AWS ENI를 이용한 설치

천재보단범재 2023. 10. 4. 21:26

AWS ENI를 이용한 설치

명령어 한 번에 Kubernetes 설치하기(2)

이전 포스팅에서 Terraform을 통해서 AWS EC2에 Kubernetes Cluster를 구성하였습니다.

 

명령어 한 번에 Kubernetes 설치하기 - Terraform으로 Kubernetes 설치

명령어 한 번에 Kubernetes 설치하기 개발 환경을 자주 구성하다 보니 Kubernetes Cluster를 구성하는 일이 많았습니다. Kubernetes Cluster 구성은 단계도 많고 쉽지 않아 할 때마다 새로웠습니다. 구성을 간

developnote-blog.tistory.com

다만 Terraform으로 구성 후 추가적인 작업이 필요하였습니다.

  • hostname 설정
  • /etc/hosts 세팅 - Master Node, Worker Node Private IP 등록
  • Master Node Kubeadm init
  • 각 Worker Node Kubeadm join

이번 포스팅에서는 AWS ENI를 이용해 Terraform을 통한 Kuberetes Cluster 구성을 보완하도록 하겠습니다.

AWS ENI

AWS ENI(Elastic Network Interface)는 VPC 내 가상 네트워크 카드입니다.

EC2를 생성하면 ENI도 생성되면서 EC2에 할당됩니다.

AWS ENI

ENI를 통해서 Public/Private IP를 할당할 수 있습니다.

EC2 인스턴스 유형에 따라서 할당 가능한 ENI 수/ IP 수가 다릅니다.

출처 : https://developnote-blog.tistory.com/manage/newpost/193?type=post&returnURL=https%3A%2F%2Fdevelopnote-blog.tistory.com%2Fmanage%2Fposts%2F

VPC내 Subnet에서 ENI를 생성합니다.

default로 리전내 가용 영역별로 Subnet이 생성되어 있습니다.

Subnet별로 CIDR Block 설정을 통해 Subnet 내에서 사용 가능한 IP가 정해져 있습니다.

따라서 ENI를 생성할 때 Subnet에서 사용 가능한 IP 주소 내에서 IP를 설정해야 합니다.

AWS ap-northeast-2 Subnet

Terraform ENI 세팅

그럼 이제 ENI를 이용해서 Terraform을 구성해 보겠습니다.

AWS ENI를 먼저 생성한 다음에 EC2에 연결해 주었습니다.

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

  required_version = ">= 1.2.0" 
}

provider "aws" {
  region = "ap-northeast-2" 
}

variable "nodes" {
  type   = map(object({
    name = string
    type = string
    docker_size = number
    volume_size = number
    public_ip = bool
    private_ip = string
  }))
  default = {
    "k8smaster" = {
      name = "k8smaster" 
      type = "t3.large" 
      docker_size = 40
      volume_size = 0
      public_ip = true
      private_ip = "172.31.36.101"
    },
    "k8sworker1" = {
      name = "k8sworker1" 
      type = "t3.xlarge" 
      docker_size = 40
      volume_size = 100
      public_ip = false
      private_ip = "172.31.36.102"
    },
    "k8sworker2" = {
      name = "k8sworker2" 
      type = "t3.xlarge" 
      docker_size = 40
      volume_size = 100
      public_ip = false
      private_ip = "172.31.36.103"
    },
    "k8sworker3" = {
      name = "k8sworker3" 
      type = "t3.xlarge" 
      docker_size = 40
      volume_size = 100
      public_ip = false
      private_ip = "172.31.36.104"
    }
  }
}

resource "aws_network_interface" "enis" {
  for_each = var.nodes

  subnet_id = "subnet-f06d9fbf"
  private_ips = ["${each.value.private_ip}"]
  security_groups = [
    "sg-7936aa07",
    "sg-01b44ac4851bcf474"
  ]
}

resource "aws_instance" "instances" {
  for_each = var.nodes

  availability_zone = "ap-northeast-2c" 
  ami               = "ami-0c9c942bd7bf113a2" # ubuntu 22.04 LTS
  instance_type     = each.value.type
  key_name          = "coxspace-teat" 
  user_data         = file("./user-data/node-install.sh")

  root_block_device {
    volume_type = "gp3" 
    volume_size = 10 # GiB
  }

  network_interface {
    network_interface_id = aws_network_interface.enis[each.value.name].id
    device_index = 0
  }

  tags = {
    Name = each.value.name
    provider = "terraform" 
  }
}

resource "aws_ebs_volume" "docker_volumes" {
  for_each = var.nodes

  availability_zone = "ap-northeast-2c" 
  size = each.value.docker_size
  type = "gp3" 

  tags = {
    Name = "${each.value.name}-vol" 
    provider = "terraform" 
  }
}

resource "aws_volume_attachment" "docker_attachements" {
  for_each = var.nodes

  device_name = "/dev/sdh" 
  volume_id   = aws_ebs_volume.docker_volumes[each.value.name].id
  instance_id = aws_instance.instances[each.value.name].id
}

resource "aws_ebs_volume" "data_volumes" {
  for_each = {
    for name, node in var.nodes : name => node
    if node.volume_size != 0
  }

  availability_zone = "ap-northeast-2c"
  size = each.value.volume_size
  type = "gp3"

  tags = {
    Name = "${each.value.name}-data-vol"
    Provider = "terraform"
    Group = "k8scluster"
  }
}

resource "aws_volume_attachment" "data_attachements" {
  for_each = {
    for name, node in var.nodes : name => node
    if node.volume_size != 0
  }

  device_name = "/dev/sdj"
  volume_id   = aws_ebs_volume.data_volumes[each.value.name].id
  instance_id = aws_instance.instances[each.value.name].id
}

resource "aws_eip" "master_ip" {
  for_each = {
    for name, node in var.nodes : name => node
    if node.public_ip == true
  }
  instance = aws_instance.instances["k8smaster"].id
  vpc      = true

  tags = {
    Name     = "k8smaster_ip" 
    provider = "terraform" 
  }
}

EC2별로 Subnet 안에서 가능한 Private IP를 세팅합니다.

그리고 필요한 Security Group도 세팅합니다.

Private IP를 미리 정하니 hostname과 /etc/hosts 세팅이 수월해졌습니다.

resource "aws_network_interface" "enis" {
  for_each = var.nodes

  subnet_id = "subnet-f06d9fbf"
  private_ips = ["${each.value.private_ip}"]
  security_groups = [
    "sg-7936aa07",
    "sg-01b44ac4851bcf474"
  ]
}

user-data script

저번에 user-data를 활용하여 Kubeadm 등 EC2에 Kubernetes Cluster 구성에 필요한 부분을 설치하였습니다.

이번에는 추가된 부분만 기입하였습니다.

AWS에서는 EC2에서 Private IP를 알 수 있는 command가 있습니다.

해당 command를 이용하여 hostname과 /etc/hosts를 세팅하였습니다.

case문을 통해서 설정한 Private IP에 따라 hostname을 세팅할 수 있었습니다.

# set hostname
PRIVATE_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4)

case $PRIVATE_IP in
  "172.31.36.101")
    HOSTNAME="k8smaster"
    ;;
  "172.31.36.102")
    HOSTNAME="k8sworker1"
    ;;
  "172.31.36.103")
    HOSTNAME="k8sworker2"
    ;;
  "172.31.36.104")
    HOSTNAME="k8sworker3"
    ;;
esac

sudo hostnamectl set-hostname $HOSTNAME

# set hostfile
cat <<EOF | sudo tee -a /etc/hosts

172.31.36.101 k8smaster
172.31.36.102 k8sworker1
172.31.36.103 k8sworker2
172.31.36.104 k8sworker3
EOF

[참고사이트]

728x90
반응형
Comments