개발 기술 블로그

REST API URI 설계 원칙 (RFC-3986)

규칙올바른 예잘못된 예
슬래시(/)는 계층 관계 표현/vehicles/suv/q6
URI 마지막에 / 미포함/vehicles/suv/q6/vehicles/suv/q6/
하이픈(-)으로 가독성 향상/vehicles/suv/qseries/6
밑줄(_) 사용 금지/vehicles/suv/q6/vehicles/suv/q_series/6
소문자 사용/vehicles/suv/q6/Vehicles/SUV/Q6
파일 확장자 미포함/vehicles/suv/q6/vehicles/suv/q6.jsp
언어 의존적 확장자 미사용/vehicles/suv/q6/vehicles/suv/q6.do
구현 의존적 경로 미사용/vehicles/suv/q6/servlet/vehicles/suv/q6
세션 ID 미포함/vehicles/suv/q6/vehicles/suv/q6?session-id=abcdef
Method명 미사용/vehicles/suv/q6/vehicles/suv/q6?action=intro
명사는 복수형 사용/vehicles/suv/q6/vehicle/suv/q6
컨트롤러는 동사/동사구/vehicles/suv/q6/re-order
CRUD는 HTTP 메서드로 표현DELETE /vehicles/q7/{car-id}GET /vehicles/q7/delete/{car-id}

CNI - Calico 네트워크 설정

  • CNI
  • 컨테이너 네트워크 표준
  • 네트워크 계층 구현 방식의 공통된 인터페이스를 제공하여 컨테이너 런타임과 오케스트레이터간의 구현방식의 난립을 방지. k8s는 Pod간 통신을 위해서 사용
  • kubernetes
  • k8s는 ‘kubenet’ 자체적 CNI Plugin을 제공하지만 매우 제한적. 3rd-party Plugin을 많이 사용함
  • CNI 필요성
  • 각 노드에 존재하는 container network의 IP대역이 동일 → Pod들이 같은 IP 할당 받을 가망성이 높음
  • 노드 별 노드 안에 있는 Pod IP만 식별 가능하기에 Pod의 IP가 다르게 할당되었다 하더라고 해당 POD가 어느 노드에 존재하는지 확인불가
  • 중복되지 않는 IP를 부여해줄 역할 → CNI Plugin
  • CNI는 worker node에 중복되지 않는 subnet부여 및 Worker node에서 실행되는 Pod는 해당 subnet에 포함된 IP를 제공 받음
  • CNI는 Pod 생성 \~ 삭제 시마다 호출되는 API 규격과 인터페이스를 정의함
  • CNI 구성 이점
  • CNI가 브릿지 인터페이스를 만들고, 컨테이너 네트워크 대역대를 나누어 테이블 생성
  • Pod들은 CNI에 의해 제공되는 고유 IP를 갖는다
  • 클러스터내의 모든 Pod간 네트워크가 자동 구성되어 Service가 없어도 Pod간 통신 가능
  • CNI Provider는 캡슐화 네트워크(VXLAN(Virtual Extensible Lan), IP-in-IP)와 비 캡슐화 네트워크(BGP(Border Gateway Protocol) 모델을 사용하여 네트워크 망 구현
  • Calico 설치(3rd-party Plugin)
  • https://docs.tigera.io/archive calico 버전 확인

HAProxy 로드밸런서 설정

######################################
# 1️⃣ HAProxy + Keepalived 설치
######################################
sudo apt update
sudo apt install -y haproxy keepalived

######################################
# 2️⃣ HAProxy 설정 (공통)
######################################
cat <<EOF | sudo tee /etc/haproxy/haproxy.cfg
global
    log /dev/log    local0
    maxconn 2000
    user haproxy
    group haproxy

defaults
    log     global
    mode    tcp
    option  tcplog
    timeout connect 10s
    timeout client 1m
    timeout server 1m

frontend k8s_apiserver
    bind *:6443
    default_backend k8s_masters

backend k8s_masters
    balance     roundrobin
    option      tcp-check
    server      master1 10.10.10.21:6443 check
    server      master2 10.10.10.22:6443 check
    server      master3 10.10.10.23:6443 check
EOF

sudo systemctl restart haproxy
sudo systemctl enable haproxy

######################################
# 3️⃣ Keepalived 설정 - master1 전용
######################################
ip link show
# ❗ NIC_NAME 변수는 실제 인터페이스 이름으로 교체 필요 (예: eth0, ens33)
NIC_NAME="eth0"

cat <<EOF | sudo tee /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state MASTER
    interface ${NIC_NAME}
    virtual_router_id 51
    priority 120
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        10.10.10.100
    }
}
EOF

sudo systemctl restart keepalived
sudo systemctl enable keepalived

######################################
# 4️⃣ Keepalived 설정 - master2 전용
######################################
# ❗ NIC_NAME 변수는 실제 인터페이스 이름으로 교체 필요 (예: eth0, ens33)
NIC_NAME="enp2s0"

cat <<EOF | sudo tee /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state BACKUP
    interface ${NIC_NAME}
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        10.10.10.100
    }
}
EOF

sudo systemctl restart keepalived
sudo systemctl enable keepalived

######################################
# ✅ VIP / 포트 / 헬스체크 확인
######################################
# VIP 확인
ip addr | grep 10.10.10.100

# 6443 포트 리슨 중인지 확인
sudo ss -ntlp | grep 6443

# API 서버 응답 확인 (API가 열려 있다면)
curl -k <https://10.10.10.100:6443/livez>

######################################
# 🚀 Kubernetes 마스터 초기화 명령어
######################################
sudo kubeadm init \\\\
  --control-plane-endpoint="10.10.10.100:6443" \\\\
  --upload-certs \\\\
  --pod-network-cidr=10.244.0.0/16

Kubernetes ConfigMap

  • 개발 , 테스트, 운영환경에 사용되는 각기 다른 환경 값의 분리 필요한 상황으로 애플리케이션 Image는 동일하게 사용하고 필요한 환경 구성값을 configMap으로 만들어 사용
  • 개발 환경은 SSH를 통한 보안 접근 해제
  • 테스트환경은 지정된 USER 및 Key를 이용한 SSH 보안 접근 사용
  • 운영환경은 테스트 환경과 다르게 지정된 USER 및 Key를 이용한 보안 접근 허용
  • 기밀이 요구되는 데이터는 secret으로 생성해 Pod에 적용해서 사용
  • 애플리케이션 레벨이 아닌 Object레벨의 환경 설정 관리 할때 사용
  • 애플리케이션 레벨에서 환경 구성 변경시 소스코드와의 의존성이 높고, 설정 값 변경 시마다 코드 수정이 불가피하여 개발속도가 지연 될 수 있다.
  • 민첩성을 강조하는 Cloud Native 환경에서 애플리케이션 개발은 애플리케이션 코드와 분리된 configMap, Secret object 사용을 통해 신속하게 적용 가능
  • configMap, Secret은 중앙 관리 방식으로 애플리케이션 코드에서 구성 및 민감한 정보를 분리하도록 설계된 Kubernetes API object → kubectl api-resources Dockerfile

Kubernetes DaemonSet

  • Deployment와 유사하지만 노드단위 배포로 이루어지기에 Replicas 옵션은 없다
  • 노드의 백그라운드에서 항상 Pod를 데몬으로 실행할 수 있게 해주는 workload resource
  • 모니터링 시스템, 로그 수집 에이전트, 노드 데이터 백업과 같은 장기간 지속되는 작업
  • 업데이트 전략 기본은 RollingeUpdate (or OnDelete)
  • “OnDelete” → 이전 데몬이 종료된 경우에만 교최
  • Taint와 toleration 옵션을 사용하여 특정 노드에 배포 선택 가능
  • 대규모 클러스터인경우 nodeSelector를 사용하여 특정 노드 선택가능
  • 로그 수집할 노드에 라벨링 → kubectl label node 노드명 log-collect-node=true