์ฟ ๋ฒ๋คํฐ์ค : Terraform์ผ๋ก ์ธ์คํด์ค ๊ด๋ฆฌ + Kubespray์ Ansible๋ก ๋ง์คํฐ1๋, ์์ปค 2๋ ์ฐ๊ฒฐ
EC2(Terraform ์คํํ ๊ณณ)์ IAM ๋ฑ๋ก (์์ EC2์์ Terraform ์คํ์์ผฐ๋๋ฐ Terraform์ ์คํํ๋ ๋
ธ๋๊ฐ ๋ ์๊ฒ ์ง?)
IAM ์ญํ ๋ง๋ค๊ธฐ
AWS ์ฝ์ → ๊ฒ์์ฐฝ์ IAM ์ ๋ ฅ → IAM ์ฝ์๋ก ์ด๋
์ผ์ชฝ ๋ฉ๋ด์์ [์ญํ ] → [์ญํ ๋ง๋ค๊ธฐ] ํด๋ฆญ
์ ๋ขฐํ ์ฃผ์ฒด ์ ํ:
AWS ์๋น์ค → EC2 ์ ํ → ๋ค์
๊ถํ ์ค์ : ์๋ ์ค ํ๋ ์ ํ
์ค์ต : AmazonEC2FullAccess
๋ ์์ ํ๊ฒ ํ๋ ค๋ฉด: AmazonEC2ReadOnlyAccess + AmazonVPCFullAccess
์ด๋ฆ: ์) terraform-k8s-role
์๋ฃ ํ ์ญํ ์์ฑ
ec2 ์์ฑํ๊ณ ip์ฃผ์ ํ์ธํด์ ์ง์ ๋ฃ์ด์ฃผ๊ธฐ ํท๊ฐ๋ฆฐ๋ค๋ฉด(๋งจ ์๋์ ์ง์ ํ๋ ๋ฐฉ๋ฒ์์) Terraform ์ ์ฌ์ฉํด๋ณด์
provider "aws" {
region = "์ํ๋๋ฆฌ์ ์
๋ ฅ"
}
variable "key_name" {
default = "ํผ๋ธ๋ฆญํค์ด๋ฆ(๋ง์คํฐ์ ์์ปค๊ฐ ํต์ ํ๋๋ฐ ์ฌ์ฉ)"
}
variable "my_ip" {
description = "Your IP address for SSH access"
default = "๋ด IP ์ฃผ์/32"
}
# ๋ณด์ ๊ทธ๋ฃน ์ค์ (๋ง์คํฐ์ ์์ปค ๋ชจ๋ ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน ์ฌ์ฉ)
# ๋ง์คํฐ ๋ฐ๋ก ์์ปค ๋ฐ๋ก ํ๋ ๊ฒ๋ ์ข์ ๋ฏ
resource "aws_security_group" "k8s_sg" {
name = "k8s-cluster-sg"
description = "Security group for Kubernetes cluster"
# SSH (22) - ๋ด IP์์๋ง SSH ์ ๊ทผ ํ์ฉ
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.my_ip] # ๋ด IP ์ฃผ์์์๋ง SSH ํ์ฉ
}
# SSH (22) - ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน ๋ด์์ SSH ์ ๊ทผ ํ์ฉ
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
source_security_group_id = aws_security_group.k8s_sg.id # ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน ๋ด์์ ์ ๊ทผ ํ์ฉ
}
# Kubernetes API (6443) - ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน ๋ด์์๋ง ์ ๊ทผ ํ์ฉ
ingress {
from_port = 6443
to_port = 6443
protocol = "tcp"
source_security_group_id = aws_security_group.k8s_sg.id
}
# etcd (2379) - ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน ๋ด์์๋ง ์ ๊ทผ ํ์ฉ
ingress {
from_port = 2379
to_port = 2379
protocol = "tcp"
source_security_group_id = aws_security_group.k8s_sg.id
}
# ๋ชจ๋ ์์๋ฐ์ด๋ ํธ๋ํฝ ํ์ฉ
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# ๋ง์คํฐ ๋
ธ๋ ์ค์
resource "aws_instance" "master" {
ami = "ami-AMI๊ณ ์ ๋ฒํธ(๋ฆฌ์ ์์ํด์๋)"
instance_type = "t3.medium"
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.k8s_sg.id] # ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน
associate_public_ip_address = true
tags = {
Name = "k8s-master"
}
}
# ์์ปค ๋
ธ๋ ์ค์
resource "aws_instance" "worker" {
count = 2
ami = "ami-AMI๊ณ ์ ๋ฒํธ(๋ฆฌ์ ์์ํด์๋)"
instance_type = "t3.large"
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.k8s_sg.id] # ๊ฐ์ ๋ณด์ ๊ทธ๋ฃน
associate_public_ip_address = false
tags = {
Name = "k8s-worker-${count.index + 1}"
}
}
# ๋ง์คํฐ ๋
ธ๋ ํผ๋ธ๋ฆญ IP ์ถ๋ ฅ
output "master_public_ip" {
value = aws_instance.master.public_ip
}
# ์์ปค ๋
ธ๋ ํ๋ผ์ด๋น IP ์ถ๋ ฅ
output "worker_private_ips" {
value = [for instance in aws_instance.worker : instance.private_ip]
}
# ๋ชจ๋ ๋
ธ๋์ ํ๋ผ์ด๋น IP ์ถ๋ ฅ
output "all_private_ips" {
value = concat(
[aws_instance.master.private_ip],
[for instance in aws_instance.worker : instance.private_ip]
)
}
cd ~/terraform-k8s
terraform plan # plan
terraform apply # apply
OUTPUT
all_private_ips = [
"๋ง์คํฐํ๋ผ์ด๋นIP",
"ํ๋ผ์ด๋น1 IP",
"ํ๋ผ์ด๋น2 IP",
]
master_public_ip = "๋ง์คํฐํผ๋ธ๋ฆญIP"
worker_private_ips = [
"ํ๋ผ์ด๋น1 IP",
"ํ๋ผ์ด๋น2 IP",
]
๋น๋ฐํค (Terraform์ ์ ์ ํผ๋ธ๋ฆญํค์ ํด๋นํ๋ ํ๋ผ์ด๋น ํค)
scp -i ํ๋ผ์ด๋น.pem ํ๋ผ์ด๋น.pem ubuntu@๋ง์คํฐํผ๋ธ๋ฆญIP:~/
mv ~/ ํ๋ผ์ด๋น.pem ~/.ssh/ ํ๋ผ์ด๋น.pem
chmod 400 ~/.ssh/ ํ๋ผ์ด๋น.pem
pipx, Ansible, Kubespray ์ค์น
# pipx ์ค์น (์ ๋์ด์๋ค๋ฉด)
sudo apt update
sudo apt install -y pipx
pipx ensurepath
# ํฐ๋ฏธ๋ ๋ค์ ์์ํ๊ฑฐ๋ ์๋ ๋ช
๋ น์ผ๋ก ์ฆ์ ์ ์ฉ
export PATH="$HOME/.local/bin:$PATH"
๋ฐ์ํ๋ ์ค๋ฅ :
× This environment is externally managed โฐโ> To install Python packages system-wide, try apt install python3-xyz, where xyz is the package you are trying to install. If you wish to install a non-Debian-packaged Python package, create a virtual environment using python3 -m venv path/to/venv. Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make sure you have python3-full installed. If you wish to install a non-Debian packaged Python application, it may be easiest to use pipx install xyz, which will manage a virtual environment for you. Make sure you have pipx installed. See /usr/share/doc/python3.12/README.venv for more information. note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages. hint: See PEP 668 for the detailed specification.
์์ธ :
Python 3.12 ์ด์์์ Debian/Ubuntu๊ฐ ์์คํ ๋ณดํธ๋ฅผ ์ํด pip์ ์ ํํ๋ ์๋ก์ด ์ ์ฑ (PEP 668)์ ๋์ ํ๋ฉด์ ์๊น
pip3 install --user ansible์ ์คํํ์ ๋
"์ด ์์คํ ์ ์ธ๋ถ ๊ด๋ฆฌ๋๋ฏ๋ก pip๋ก ์ง์ ์ค์นํ์ง ๋ง๊ณ , ๊ฐ์ํ๊ฒฝ(venv) ๋๋ apt/pipx๋ฅผ ์จ๋ผ"
ํด๊ฒฐ ๋ฐฉ์ :
sudo apt install pipx
pipx install ansible
# Ansible ์ค์น
pipx install ansible
# ์ฌ์ฉ ์์
ansible --version
# ์์
๋๋ ํ ๋ฆฌ ์์ฑ ๋ฐ kubespray ๋ค์ด๋ก๋
mkdir -p ~/k8s-kubespray && cd ~/k8s-kubespray
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray
# kubespray ์์กด์ฑ ์ค์น๋ฅผ ์ํ ์ ์ฉ venv ์์ฑ
python3 -m venv .venv
source .venv/bin/activate
# kubespray requirements ์ค์น
pip install -r requirements.txt
# kubespray ๋๋ ํ ๋ฆฌ ์ง์
์์๋ ์์กด์ฑ์ฉ ๊ฐ์ํ๊ฒฝ ํ์ฑํ ํ์
cd ~/k8s-kubespray/kubespray
source .venv/bin/activate
deactivate
hosts.ini ์์ฑ
# (.venv) ubuntu@ip-๋ง์คํฐ:~/k8s-kubespray/kubespray/inventory/mycluster$ ls
nano make-hosts.sh
chmod +x make-hosts.sh
make-hosts.sh (OUTPUT์ ๋์์๋ IP ์ฃผ์ ์ฐธ๊ณ ํด์ ์์ฑ)
#!/bin/bash
# Terraform output์์ ๊ฐ ์ฝ๊ธฐ
MASTER_PRIVATE_IP=$(terraform output -raw all_private_ips | awk -F '"' '{print $2}')
WORKER_PRIVATE_IPS=($(terraform output -json worker_private_ips | jq -r '.[]'))
MASTER_PUBLIC_IP=$(terraform output -raw master_public_ip)
KEY_PATH="~/.ssh/๋น๋ฐํค.pem" # ํ์ํ ๊ฒฝ์ฐ ๊ฒฝ๋ก ์์ ๊ฐ๋ฅ
# INI ํ์์ผ๋ก ์ถ๋ ฅ
cat <<EOF > ./inventory/mycluster/hosts.ini
[all]
master ansible_host=๋ง์คํฐํ๋ผ์ด๋นIP ip=๋ง์คํฐํ๋ผ์ด๋นIP access_ip=๋ง์คํฐํผ๋ธ๋ฆญIP ansible_ssh_private_key_file=~/.ssh/๋น๋ฐํค.pem
worker1 ansible_host=์์ปคํ๋ผ์ด๋นIP ip=์์ปคํ๋ผ์ด๋นIP ansible_ssh_private_key_file=~/.ssh/๋น๋ฐํค.pem
worker2 ansible_host=์์ปคํ๋ผ์ด๋นIP ip=์์ปคํ๋ผ์ด๋นIP ansible_ssh_private_key_file=~/.ssh/๋น๋ฐํค.pem
[kube_control_plane]
master
[etcd]
master
[kube_node]
worker1
worker2
[k8s_cluster:children]
kube_control_plane
kube_node
EOF
echo "โ
hosts.ini ์์ฑ ์๋ฃ → ./inventory/mycluster/hosts.ini"
ansible-playbook ๋ช ๋ น ์คํํ์ฌ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ์ค์น ์๋ฃ
cd ~/k8s-kubespray/kubespray
source .venv/bin/activate
ansible-playbook -i inventory/mycluster/hosts.ini \
--become --become-user=root cluster.yml
kubectl ์ค์น (Kubespray๋ kubeadm๊ณผ ๋ค๋ฅด๊ฒ ์๋์ผ๋ก ์ค์น ์ํด์ค)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client
kubectl get ๋ช ๋ น์ด๋ค์ด ํด๋ฌ์คํฐ์ ํต์ ํ๊ธฐ ์ํด ํ์ํจ
sudo chmod 644 /etc/kubernetes/admin.conf
echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >> ~/.bashrc
source ~/.bashrc

๋ณด์ ๊ทธ๋ฃน์ด๋ ๋ง์คํฐ ๋ ธ๋ ๊ฐ์ฉ์ฑ ๊ด๋ จํด์ ํ ๋ง์ด ๋ง์ง๋ง
1๋ ํ๋ก์ ํธ์ด๋ฏ๋ก ๋์ค์ ์ ์ฉํ๋ ๊ฑธ๋ก ํ์
inventory ์๋ ์์ฑ
cat <<EOF > ../hosts.txt
[๋ง์คํฐIP]
[์์ปค1 IP]
[์์ปค2 IP]
EOF
1) SSH ๋น๋ฐ๋ฒํธ ์์ด ์ ์ํ ์ ์๋๋ก ๊ณต๊ฐ ํค๋ฅผ ๋ง๋๋ ๊ณผ์
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
2) ์ด ํค๋ฅผ ๊ฐ ๋ ธ๋๋ก ๋ณต์ฌ
while read ip; do
sshpass -p '๋น๋ฐ๋ฒํธ' ssh-copy-id -o StrictHostKeyChecking=no root@$ip
done < ../hosts.txt
IP ๋ฆฌ์คํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก inventory/mycluster/hosts.yaml ํ์ผ์ ์๋์ผ๋ก ๋ง๋ค์ด์ค
declare -a IPS=([๋ง์คํฐIP] [์์ปค1 IP] [์์ปค2 IP])
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
์ฟ ๋ฒ๋คํฐ์ค์ ํ์ํ ์ญํ ์ ์๋์ผ๋ก ๋๋ ์ค
์ฒซ๋ฒ์งธ IP : ๋ง์คํฐ
๋๋จธ์ง : ์์ปค
source .venv/bin/activate
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml
| [์ฟ ๋ฒ๋คํฐ์ค] concepts/overview/working-with-objects/names (0) | 2025.09.10 |
|---|---|
| [์ฟ ๋ฒ๋คํฐ์ค] Self-healing ์์ฝ (0) | 2025.08.12 |
| ์ฟ ๋ฒ๋คํฐ์ค ์ค์น : ์คํจ (๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ; ์ต์ t3.medium์ ํด์ผ ํจ) (0) | 2025.04.02 |
| [Kubernetes for the Absolute Beginners] Kubernetes Concepts : Pods (0) | 2025.03.18 |
| [Kubernetes - 1] Docker : ์ปจํ ์ด๋๊ฐ ํ์ํ ์ด์ (0) | 2025.03.03 |