일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- log
- grafana
- kubernetes
- Packet
- airflow
- Operating System
- Spring
- CVAT
- zookeeper
- EC2
- aws s3
- helm
- OS
- JavaScript
- Vision
- PostgreSQL
- java
- jvm
- ip
- AWS
- Python
- kubeadm
- Network
- Trino
- tcp
- kubectl
- docker
- MAC address
- CSV
- Kafka
- Today
- Total
JUST WRITE
명령어 한 번에 Kubernetes 설치하기 - Terraform으로 Kubernetes 설치 본문
명령어 한 번에 Kubernetes 설치하기
개발 환경을 자주 구성하다 보니 Kubernetes Cluster를 구성하는 일이 많았습니다.
Kubernetes Cluster 구성은 단계도 많고 쉽지 않아 할 때마다 새로웠습니다.
구성을 간편하게 할 수 있는 방법이 없을까 고민하다가 Terraform을 알게 되었습니다.
Terraform을 활용하여 간편하게 Kubernetes Cluster를 구성하는 것을 정리해보려 합니다.
(Terraform이 아닌 AWS EC2 다수의 인스턴스로 Kubernetes를 구성하는 것은 아래 포스팅 참조)
What is Terraform?
Terraform은 오픈 소스로 IaC(Infrastructure as Code) Tool입니다.
IaC는 Storage, Network 등 Infra를 Code로 관리하는 것을 의미합니다.
Terraform을 통해서 Cloud나 On-premise 환경의 Resouce들을 Code로 관리할 수 있습니다.
Terraform은 Provider를 통해서 해당 Resource를 관리합니다.
작성한 Terraform Code를 실행하며 Provider가 Resource의 API를 통해 Resource에 반영합니다.
Provider들은 Terraform Registry에서 확인할 수 있습니다.
AWS, GCP, Kubernetes, Helm, DataDog 등 다양한 Provider들을 제공합니다.
Terraform 설치
일단 Terraform 설치를 진행해 보겠습니다.
AWS EC2, Amazon Linux 2023 AMI 인스턴스에 설치를 진행하였습니다.
Terraform bin 파일을 Download 합니다.
$ wget https://releases.hashicorp.com/terraform/1.4.6/terraform_1.4.6_linux_amd64.zip
$ unzip terraform_1.4.6_linux_amd64.zip
$ ll
total 83408
-rwxr-xr-x. 1 ec2-user ec2-user 64626688 Apr 26 17:54 terraform
-rw-r--r--. 1 ec2-user ec2-user 20779821 Apr 26 18:26 terraform_1.4.6_linux_amd64.zip
bin 파일을 PATH에 위치시켜 어디에서든 command를 실행할 수 있도록 합니다.
$ mkdir -p ~/.local/bin
$ mv terraform ~/.local/bin
$ terraform
Usage: terraform [global options] <subcommand> [args]
The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.
Main commands:
init Prepare your working directory for other commands
validate Check whether the configuration is valid
plan Show changes required by the current configuration
apply Create or update infrastructure
destroy Destroy previously-created infrastructure
All other commands:
console Try Terraform expressions at an interactive command prompt
fmt Reformat your configuration in the standard style
force-unlock Release a stuck lock on the current workspace
get Install or upgrade remote Terraform modules
graph Generate a Graphviz graph of the steps in an operation
import Associate existing infrastructure with a Terraform resource
login Obtain and save credentials for a remote host
logout Remove locally-stored credentials for a remote host
metadata Metadata related commands
output Show output values from your root module
providers Show the providers required for this configuration
refresh Update the state to match remote systems
show Show the current state or a saved plan
state Advanced state management
taint Mark a resource instance as not fully functional
test Experimental support for module integration testing
untaint Remove the 'tainted' state from a resource instance
version Show the current Terraform version
workspace Workspace management
Global options (use these before the subcommand, if any):
-chdir=DIR Switch to a different working directory before executing the
given subcommand.
-help Show this help output, or the help for a specified subcommand.
-version An alias for the "version" subcommand.
AWS Config 설정
Terraform으로 Kubernetes 구성은 AWS EC2 인스턴스들을 띄워서 구성할 예정입니다.
Terraform AWS Provider를 통해서 구성합니다.
AWS EC2 인스턴스를 시작할 수 있는 권한을 가진 IAM User가 필요합니다.
IAM에서 AmazonEC2FullAccess 권한을 가진 User를 생성하였습니다.
해당 User의 access-key, secret-key를 Terraform 실행할 Server에 등록합니다.
aws cli를 통해서 등록하거나 credentials 파일을 직접 생성합니다.
# 1. aws command
$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
Default output format [None]:
# 2. credentials 파일 생성
$ vi ~/.aws/credentials
[default]
aws_access_key_id = ${access-key}
aws_secret_access_key = ${secret-key}
이제 Terraform을 사용할 준비는 마쳤습니다.
Kubernetes 설치
솔직히 말하면 commad 하나로 Kubernetes Cluster 구성을 하지 못했습니다.
Terramform으로 구성 후 몇 가지 추가 작업이 필요합니다.
하지만 Terraform으로 통한 Kubernetes 구성 작업량은 상당히 줄어들었습니다.
일단 Terraform Code를 살펴보도록 하겠습니다.
Terraform Code
Terraform을 통해 AWS EC2 Instance 4개, Elastic IP, EBS(Elastic Block Store)가 설치됩니다.
EC2 Instance 4개는 Kuberentes Master Node 1개, Worker Node 3개로 구성됩니다.
Terraform 전체 Code는 아래와 같습니다.
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
size = number
}))
default = {
"k8smaster" = {
name = "k8smaster"
type = "t3.large"
size = "20"
},
"k8sworker1" = {
name = "k8sworker1"
type = "t3.xlarge"
size = "40"
},
"k8sworker2" = {
name = "k8sworker2"
type = "t3.xlarge"
size = "40"
},
"k8sworker3" = {
name = "k8sworker3"
type = "t3.xlarge"
size = "40"
}
}
}
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 = ${key-name}
user_data = file("./user-data/node-install.sh")
vpc_security_group_ids = [
${security-group-id1},
${security-group-id2}
]
root_block_device {
volume_type = "gp3"
volume_size = 10 # GiB
}
tags = {
Name = each.value.name
provider = "terraform"
}
}
resource "aws_ebs_volume" "volumes" {
for_each = var.nodes
availability_zone = "ap-northeast-2c"
size = each.value.size
type = "gp3"
tags = {
Name = "${each.value.name}-vol"
provider = "terraform"
}
}
resource "aws_volume_attachment" "attachements" {
for_each = var.nodes
device_name = "/dev/sdh"
volume_id = aws_ebs_volume.volumes[each.value.name].id
instance_id = aws_instance.instances[each.value.name].id
}
resource "aws_eip" "master_ip" {
instance = aws_instance.instances["k8smaster"].id
vpc = true
tags = {
Name = "k8smaster_ip"
provider = "terraform"
}
}
Variable을 통해 EC2 Instance로 설치한 Master Node, Worker Node 정보들을 기입하였습니다.
- Instance 이름
- Instance Type
- 추가 EBS Size
variable "nodes" {
type = map(object({
name = string
type = string
size = number
}))
default = {
"k8smaster" = {
name = "k8smaster"
type = "t3.large"
size = "20"
},
"k8sworker1" = {
name = "k8sworker1"
type = "t3.xlarge"
size = "40"
},
"k8sworker2" = {
name = "k8sworker2"
type = "t3.xlarge"
size = "40"
},
"k8sworker3" = {
name = "k8sworker3"
type = "t3.xlarge"
size = "40"
}
}
}
Terraform에서는 반복문을 사용할 수 있습니다.
for_each라는 구문을 활용하여 반복적인 EC2 Instance 생성 부분을 간략하게 할 수 있었습니다.
위에서 정의한 Instance 정보들을 기입한 Variable으로 for문을 진행하였습니다.
EBS 역시 같은 방식으로 for문을 진행하였습니다.
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 = ${key-name}
user_data = file("./user-data/node-install.sh")
vpc_security_group_ids = [
${security-group-id1},
${security-group-id2}
]
root_block_device {
volume_type = "gp3"
volume_size = 10 # GiB
}
tags = {
Name = each.value.name
provider = "terraform"
}
}
AWS Instance를 실행할 때 user-data를 활용하여 시작 시 script를 실행할 수 있습니다.
user-data를 이용하여 Kubernetes 설치에 필요한 작업들을 script로 정리하여 실행하였습니다.
script에서 진행하는 작업은 아래와 같습니다.
- swap off
- EBS mount
- Docker 설치
- cri-dockerd 설치
- kubeadm, kubectl, kubelet 설치
#!/bin/bash
# swap off
sudo swapoff -a
# EBS mount
sudo mkfs.ext4 /dev/nvme1n1
sudo mkdir /data -p
echo '/dev/nvme1n1 /data ext4 defaults 0 0' | sudo tee -a /etc/fstab > /dev/null
sudo mount -a
# network plugin setting
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# sysctl params setting
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
# docker install
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg -y
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin -y
sudo mkdir /data/docker_dir -p
sudo tee -a /etc/docker/daemon.json > /dev/null << EOT
{
"data-root": "/data/docker_dir"
}
EOT
sudo systemctl enable docker --now
sudo systemctl restart docker
# cri-dockerd install
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.2/cri-dockerd_0.3.2.3-0.ubuntu-jammy_amd64.deb
sudo dpkg -i cri-dockerd_0.3.2.3-0.ubuntu-jammy_amd64.deb
rm cri-dockerd_0.3.2.3-0.ubuntu-jammy_amd64.deb
# k8s install
sudo apt-get install -y apt-transport-https ca-certificates curl
#sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
#echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
script 작업에 대한 자세한 설명은 아래 포스팅에서 확인할 수 있습니다.
마지막으로 Master Node로 설치한 Instance에 Elastic IP를 연결합니다.
외부에서 Master Node로 통해 Kubernetes에 접근하기 때문에 Master Node에만 연결합니다.
resource "aws_eip" "master_ip" {
instance = aws_instance.instances["k8smaster"].id
vpc = true
tags = {
Name = "k8smaster_ip"
provider = "terraform"
}
}
Terraform 실행
이제 Terraform 실행을 합니다.
Terraform init command를 통해 AWS Provider를 설치합니다.
$ terraform init
$ cd .terraform
$ tree
.
└── providers
└── registry.terraform.io
└── hashicorp
└── aws
└── 4.67.0
└── linux_amd64
└── terraform-provider-aws_v4.67.0_x5
validate command로 작성한 terraform code를 실행 전에 검증합니다.
$ terraform validate
Success! The configuration is valid.
이제 작성한 terraform code를 AWS에 적용해 봅니다.
# 적용, auto-approve 인자를 넣으면 마지막 확인 절차 진행 X
$ terraform apply -auto-approve
AWS Console에서 EC2 Instance 4개가 생성된 것을 확인할 수 있습니다.
Terraform을 통해서 EC2 Instance를 설치하고 docker, kubeadm까지 설치하였습니다.
남은 작업은 아래와 같습니다.
- hostname 설정
- /etc/hosts 세팅 - Master Node, Worker Node Private IP 등록
- Master Node Kubeadm init
- 각 Worker Node Kubeadm Join
Node마다 command가 다른 부분, Join 할 때 Token 기입 부분은 Terrform으로 아직 해결하지 못했습니다.
조금 더 보완해서 해당 부분까지 Terraform으로 해결하도록 Version 2를 만들도록 하겠습니다.
[보완]
추가적으로 이번 포스팅에서 Kubernetes의 Container runtime을 docker로 설치하였습니다.
kubeadm으로 init, join시 해당 parameter를 추가해줘야 합니다.
- --cri-socket unix:///var/run/cri-dockerd.sock
# kubeadm init(Mater node)
$ sudo kubeadm init --control-plane-endpoint=k8smaster --apiserver-advertise-address=${control_plain_ip} --pod-network-cidr=10.244.0.0/16 --cri-socket unix:///var/run/cri-dockerd.sock
# kubeadm join(Worker node)
$ sudo kubeadm join k8smaster:6443 --token ${token} --discovery-token-ca-cert-hash ${hash} --cri-socket unix:///var/run/cri-dockerd.sock
'MLOps > Kubernetes' 카테고리의 다른 글
손쉽게 동적으로 Persistent Volume 생성하기 (0) | 2023.06.15 |
---|---|
[Ingress] ArgoCD UI 헷갈리지 않고 쉽게 접근하기 (0) | 2023.06.04 |
Kubernetes에 CVAT 설치하기 - Helm으로 CVAT 설치 (8) | 2023.05.05 |
특정 Node에 Pod 스케줄링 (0) | 2023.02.26 |
Kubernets Cluster에 Worker Node 추가 (0) | 2023.02.18 |