처누

[Infra] 마스터 노드 구축 본문

카테고리 없음

[Infra] 마스터 노드 구축

처누 2025. 5. 4. 13:18

인스턴스들의 보안 그룹에서 인바운드 규칙을 설정해주어야 한다.

Calico를 사용하기로 했기 때문에 아래와 같이 설정을 해주었다.

모든 노드 공통

프로토콜 포트 출발지(CIDR) 설명
TCP 6443 모든 IP Kubernetes API 서버 (kubectl 등 클라이언트가 접근)
TCP 2379-2380 서브넷 IPv4 CIDR etcd 통신
TCP 10250 서브넷 IPv4 CIDR Kubelet API (metrics-server, kubectl logs 등)
TCP 10255 서브넷 IPv4 CIDR (선택) Kubelet 읽기 전용 포트 (보안상 권장 안됨)
TCP 30000-32767 모든 IP NodePort 서비스용 포트 (외부에서 접근)
       

마스터 노드에 필요한 포트

프로토콜 포트 출발지(CIDR) 설명
TCP 10251 서브넷 IPv4 CIDR kube-scheduler
TCP 10252 서브넷 IPv4 CIDR kube-controller-manager
TCP 10259 서브넷 IPv4 CIDR (v1.20+) scheduler
TCP 10257 서브넷 IPv4 CIDR (v1.20+) controller-manager

Calico에 필요한 포트

프로토콜 포트 출발지(CIDR) 설명
TCP/UDP 179 서브넷 IPv4 CIDR BGP 포트 (Calico의 default 통신 방식)
UDP 4789 서브넷 IPv4 CIDR VXLAN UDP 포트
TCP 5473 서브넷 IPv4 CIDR Felix가 Typha와 통신하기 위한 포트

1. 시스템 초기 설정

# 스왑 비활성화
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

# iptables가 브릿지 트래픽을 확인하도록 설정
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

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

2. 컨테이너 런타임 설치(containerd 사용)

# 필요한 패키지 설치
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

# Docker 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Docker 저장소 추가
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# containerd 설치
sudo apt update
sudo apt install -y containerd.io

# containerd 구성
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

3. 쿠버네티스 저장소 설정(v1.30)

최신 버전으로 시도했으나 버전 충돌 에러로 인해 1.30으로 설치

sudo curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo 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.30/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

4. kubeadm을 사용한 마스터 노드 초기화

kubeadm-config.yaml

#kubeadm-config.yaml

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.30.0
controlPlaneEndpoint: <마스터노드에 연결된 EIP>:6443
networking:
  podSubnet: 192.168.0.0/16 #Calico 기본 네트워크
apiServer:
  timeoutForControlPlane: 4m0s
  extraArgs:
    enable-admission-plugins: NodeRestriction
    service-account-issuer: https://kubernetes.default.svc.cluster.local
    service-account-signing-key-file: /etc/kubernetes/pki/sa.key
    service-account-key-file: /etc/kubernetes/pki/sa.pub
controllerManager:
  extraArgs:
    bind-address: 0.0.0.0
scheduler:
  extraArgs:
    bind-address: 0.0.0.0
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
  criSocket: /run/containerd/containerd.sock
  name: master-node
  taints:
  - key: node-role.kubernetes.io/control-plane
    effect: NoSchedule
apiServer:
  timeoutForControlPlane: 4m0s
  extraArgs:
    enable-admission-plugins: NodeRestriction
    service-account-issuer: https://kubernetes.default.svc.cluster.local
    service-account-signing-key-file: /etc/kubernetes/pki/sa.key
    service-account-key-file: /etc/kubernetes/pki/sa.pub
  • enable-addmission-plugins : NodeRestriction(보안상 필수)
    • NodeRestriction 플러그인은 kubelet이 자기 노드에 속한 리소스만 수정할 수 있도록 제한하는 역할을 함.
    • 예를 들어, 어떤 노드의 kubelet이 다른 노드의 Pod나 Node 리소스를 건드릴 수 없게 막아주는 것.
  • service-account-issuer, service-account-signing-key-file, service-account-key-file(필수)
    • Service Account Token Volume Projection 기능을 제대로 쓰기 위한 설정.
    • 쿠버네티스가 Pod에 JWT 토큰을 발급할 때, 그 토큰의 issuer가 뭔지 명시해주는 것, 해당 토큰을 사인(sign)하는 키도 명시하는 것.
    • 쿠버네티스 1.22 이후부턴 필수
    • OIDC 연동이나 외부 인증 시스템을 붙일거라면 꼭 필요함.
sudo kubeadm init --config=kubeadm-config.yaml

kubeadm join으로 시작하는 명령어는 따로 저장해놓자!

5. kubectl 설정

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

6. 네트워그 플러그인 설치(Calico)

 

custom-resoucers.yaml

# This section includes base Calico installation configuration.
# For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    bgp: Disabled
    ipPools:
    - name: default-ipv4-ippool
      blockSize: 26
      cidr: 192.168.0.0/16
      encapsulation: VXLAN
      natOutgoing: Enabled
      nodeSelector: all()

---

# This section configures the Calico API server.
# For more information, see: https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.APIServer
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
  name: default
spec: {}

 

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.4/manifests/tigera-operator.yaml
kubectl create -f custom-resources.yaml

 

게시글 작성일 기준 Calico 최신 버전인 3.29 설치 중 아래와 같은 에러가 발생했다.

The CustomResourceDefinition "installations.operator.tigera.io" is invalid: metadata.annotations: Too long: must have at most 262144 bytes

kubectl apply 명령어가 리소스를 적용할 때, 해당 리소스의 메타데이터에 `kubectl.kubernetes.io/last-applied-configuration`라는 주석을 추가하는데 이 주석이 너무 커서 발생하는 문제였다.
쿠버네티스를 여러번 설치해보면서 버전 문제로 인한 에러가 많았기에 한 버전 낮은 버전으로 설치했다.

공식문서를 보면 custom-resources.yaml 설치 명령어가 아래와 같이 돼있다.

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.4/manifests/custom-resources.yaml

 

하지만 해당 custom-resources.yaml을 열어보면 BGP가 Enabled로 돼있다.

calicoNetwork:
  bgp: Enabled

 

Calico는 기본값으로 BGP 모드(BIRD 데몬 사용)를 활성화한다.

여기서 문제가 발생했다. 워커노드 조인 후 calico-node가 Running 상태였지만 READY0/1로 돼있었다.

에러 로그는 다음과 같았다.

calico/node is not ready: BIRD is not ready: BGP not established with


Calico가 BGP를 통해 노드 간 네트워크를 연결하려고 하지만 연결에 실패한 것.
단일 클러스터이거나 클러스터 간 BGP 피어가 없을 때, BGP 모드를 사용하면 BIRD가 외롭게 떠 있다가 계속 에러를 발생시킨다고 한다.
따라서 BGP 대신 VXLAN을 선택했다.

VXLAN을 사용한 이유

  • AWS EC2 환경에서는 BGP 구성이 번거롭고 불필요함
    • BGP를 사용하려면 EC2 간 IPsec 터널이나 외부 라우터, 또는 노드 간 BGP 피어링 구성이 필요함.
    • 이는 추가적인 설정 부담과 복잡한 보안 정책, 라우팅을 요구함.
  • VXLAN은 오버레이 네트워크이므로 인프라 제약 없이 작동
    • 노드 간 직접 라우팅이 없어도 VXLAN 터널을 통해 Pod 간 통신이 가능.
    • 따라서 클라우드 환경이나 VPC 내부 통신만 허용된 환경에서 매우 적합.
    • EC2 노드 간의 VPC 통신만 되면 VXLAN이 자동으로 IP를 캡슐화하여 라우팅 처리해줌.
  • VPC 환경에서는 VPC 라우팅과 BGP 충돌 위험이 있음
    • AWS의 기본 라우팅 테이블과 BGP 경로가 충돌하거나 비효율적인 경로를 만들 수 있음.
    • VXLAN을 쓰면 노드 간 트래픽은 VPC 경로를 그대로 사용하면서, 내부적으로 Pod 트래픽을 깔끔하게 캡슐화함.
  • Calico 공식 문서도 클라우드 환경에서는 VXLAN을 권장
    • 특히 AWS, GCP, Azure 같은 퍼블릭 클라우드 환경에선 대부분 BGP 대신 VXLAN을 기본 권장합니다.

7. 설치 확인

kubectl get pods -n calico-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-6778c58446-kv8kn   1/1     Running   0          19h
calico-node-ttpsg                          1/1     Running   0          19h
calico-typha-556858b96d-btrjs              1/1     Running   0          19h
csi-node-driver-ghh88                      2/2     Running   0          19h

kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
master-node   Ready    control-plane   20h   v1.30.12

kubectl get pods -A
NAMESPACE          NAME                                       READY   STATUS    RESTARTS   AGE
calico-apiserver   calico-apiserver-88cc84d78-9jlcw           1/1     Running   0          19h
calico-apiserver   calico-apiserver-88cc84d78-hg6px           1/1     Running   0          19h
calico-system      calico-kube-controllers-6778c58446-kv8kn   1/1     Running   0          19h
calico-system      calico-node-ttpsg                          1/1     Running   0          19h
calico-system      calico-typha-556858b96d-btrjs              1/1     Running   0          19h
calico-system      csi-node-driver-ghh88                      2/2     Running   0          19h
kube-system        coredns-55cb58b774-gq4dw                   1/1     Running   0          20h
kube-system        coredns-55cb58b774-t4kgw                   1/1     Running   0          20h
kube-system        etcd-master-node                           1/1     Running   0          20h
kube-system        kube-apiserver-master-node                 1/1     Running   0          20h
kube-system        kube-controller-manager-master-node        1/1     Running   0          20h
kube-system        kube-proxy-zpjm9                           1/1     Running   0          20h
kube-system        kube-scheduler-master-node                 1/1     Running   0          20h
tigera-operator    tigera-operator-8955b7496-6zs7w            1/1     Running   0          19h  

우여곡절 끝에 마스터 노드 설정 완료!!! 이제 다음은 워커 노드 설정과 도메인 등록, helm, argocd 등등 할게 많이 남았다!