Kubernetes 패킷 흐름을 분석하려면 Local Pc에 K8S 클러스터를 구축하는 편이 좋다.
EKS 등 관리형 Kubernets를 사용할수도 있지만, 패킷 트레이싱이 비교적 까다롭다.
무엇보다
집에 남는 PC가 있다면 전기세만 부담하면되기 때문에 비용도 저렴하다. 😃
최근 들어서 Input만 있고, Input에 대해 정리하는 시간이 없었어서
조금 느리더라도 Output에 집중해보려고한다.
환경 구성
- Kubernetes 버전 : 1.29
- CNI : Calico
- Route Mode : Iptable
- OS : Ubuntu
- VM 프로비저닝 툴 : Vagrant
virtualbox안에서 실행되기 때문에 OS는 관계 없다.
개인적으로는 Ubuntu가 향후 다른 서버를 운영하기에도 편리하고,
SSH로 접근이 가능하기 떄문에 Ubuntu 안에 K8S Cluster를 구축했다.
(윈도우 10을 서버처럼 운영하려하니 자꾸 이상한 OS Level에서 오류나면서 PC가 꺼져서 포기했다)
설치 과정은 다음과 같이 심플하다.
1. vagrant, Virtualbox를 OS에 설치
2. 아래 제공된 Vagrantfile, master-node.sh, worker-node.sh 파일을 한 경로에 두고,
3. 해당 파일이 있는 곳에서 vagrant up 명령어만 입력하면, Kubernetes 클러스터가 구축된다.
이전에는 Vagrantfile과 스크립트 만드는데에도 한 세월이었는데...
GPT 사용하니 완벽한 환경 구성까지 2시간이 채 걸리지 않았다....
# Vagrantfile, master-node.sh, worker-node.sh 파일이 있는 경로로 이동 한후
vagrant up
Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
MASTER_IP = "192.168.56.10"
NODE_IP_NW = "192.168.56."
NODE_IP_START = 11
NUM_WORKER_NODES = 2
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/focal64"
config.vm.box_check_update = false
# Master Node
config.vm.define "k8s-master" do |master|
master.vm.hostname = "k8s-master"
master.vm.network "private_network", ip: MASTER_IP, virtualbox__intnet: false
master.vm.network "forwarded_port", guest: 6443, host: 6443, host_ip: "192.168.0.7"
master.vm.provider "virtualbox" do |vb|
vb.memory = 2048
vb.cpus = 2
vb.name = "k8s-master"
end
master.vm.provision "shell", path: "master-node.sh"
end
# Worker Nodes
(1..NUM_WORKER_NODES).each do |i|
config.vm.define "k8s-worker-#{i}" do |worker|
worker.vm.hostname = "k8s-worker-#{i}"
worker.vm.network "private_network", ip: "#{NODE_IP_NW}#{NODE_IP_START + i}", virtualbox__intnet: false
worker.vm.provider "virtualbox" do |vb|
vb.memory = 8196
vb.cpus = 4
vb.name = "k8s-worker-#{i}"
end
worker.vm.provision "shell", path: "worker-node.sh"
end
end
# 모든 노드에 대한 공통 설정
config.vm.provision "shell", inline: <<-SHELL
# IP 포워딩 활성화
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# iptables 설정
iptables -P FORWARD ACCEPT
iptables -A FORWARD -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# 필요한 커널 모듈 로드
modprobe br_netfilter
echo "br_netfilter" >> /etc/modules
# 브리지 네트워크 설정
echo "net.bridge.bridge-nf-call-iptables=1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables=1" >> /etc/sysctl.conf
sysctl -p
SHELL
end
master-node.sh
#!/bin/bash
# 시스템 업데이트 및 기본 패키지 설치
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# Docker 설치
apt-get install -y docker.io
systemctl enable docker
systemctl start docker
# Docker 데몬 설정
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
systemctl restart docker
# Kubernetes 새로운 repo 키 및 저장소 추가
mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
# Kubernetes 컴포넌트 설치
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
# swap 비활성화
swapoff -a
sed -i '/swap/d' /etc/fstab
# 필요한 모듈 로드
modprobe br_netfilter
modprobe overlay
# 시스템 설정
cat <<EOF | 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
sysctl --system
# Master 노드 초기화
INTERNAL_IP="192.168.56.10" # master node의 고정 IP
HOST_IP="0.0.0.0"
kubeadm init --apiserver-advertise-address=$INTERNAL_IP --apiserver-cert-extra-sans=$HOST_IP --node-name=$(hostname -s) --pod-network-cidr=192.168.0.0/16 --ignore-preflight-errors=all > /root/kubeadm-init.output
# kubelet 설정 추가
cat > /etc/default/kubelet << EOF
KUBELET_EXTRA_ARGS=--node-ip=$INTERNAL_IP
EOF
# kubelet 재시작
systemctl restart kubelet
# kubeconfig 설정
mkdir -p /home/vagrant/.kube
cp -i /etc/kubernetes/admin.conf /home/vagrant/.kube/config
chown -R vagrant:vagrant /home/vagrant/.kube
# root 사용자를 위한 kubeconfig 설정
export KUBECONFIG=/etc/kubernetes/admin.conf
# Calico Operator 설치
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/tigera-operator.yaml
# CRD가 완전히 생성될 때까지 대기
echo "Waiting for Calico CRDs to be ready..."
sleep 30
# Installation CR 생성
cat <<EOF | kubectl create -f -
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- blockSize: 26
cidr: 192.168.0.0/16
encapsulation: None
natOutgoing: "Enabled"
nodeSelector: all()
EOF
# Calico pods가 실행될 때까지 대기
echo "Waiting for Calico pods to be ready..."
kubectl wait --for=condition=ready pod -l k8s-app=calico-node -n calico-system --timeout=90s
# kube-proxy iptables 모드 설정
kubectl -n kube-system get configmap kube-proxy -o yaml | sed 's/mode: ""/mode: "iptables"/' | kubectl replace -f -
kubectl -n kube-system delete pod -l k8s-app=kube-proxy
# Join 커맨드 저장
cat /root/kubeadm-init.output | grep -A 2 "kubeadm join" > /vagrant/join.sh
chmod +x /vagrant/join.sh
worker-node.sh
#!/bin/bash
# 시스템 업데이트 및 기본 패키지 설치
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
# Docker 설치
apt-get install -y docker.io
systemctl enable docker
systemctl start docker
# Docker 데몬 설정
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
systemctl restart docker
# Kubernetes 새로운 repo 키 및 저장소 추가
mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
# Kubernetes 컴포넌트 설치
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
# swap 비활성화
swapoff -a
sed -i '/swap/d' /etc/fstab
# 필요한 모듈 로드
modprobe br_netfilter
modprobe overlay
# 시스템 설정
cat <<EOF | 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
sysctl --system
# 파일 상단에 추가
INTERNAL_IP=$(ip -f inet addr show enp0s8 2>/dev/null | grep -Po 'inet \K[\d.]+')
# kubeadm join 명령어 실행 전에 추가
echo "KUBELET_EXTRA_ARGS=--node-ip=$INTERNAL_IP" > /etc/default/kubelet
systemctl restart kubelet
# Master 노드에 Join
bash /vagrant/join.sh