카테고리 보관물: infra

[Kubernetes] Understanding how the Calico CNI works

[Kubernetes] Calico CNI 동작원리 이해하기

  • Calico란, 컨테이너, 가상 머신 및 기본 호스트 기반 워크로드를 위한 오픈 소스 네트워킹 및 네트워크 보안 솔루션이다.
  • Kubernetes, OpenShift, Mirantis Kubernetes Engine(MKE), OpenStack 및 베어메탈 서비스를 포함한 광범위한 플랫폼 지원한다.
  • Calico의 eBPF 데이터 플레인을 사용하든 Linux의 표준 네트워킹 파이프라인을 사용하든 Calico는 진정한 클라우드 네이티브 확장성과 함께 놀랍도록 빠른 성능을 제공한다.
  • Calico는 공용 클라우드나 온프레미스, 단일 노드 또는 수천 개의 노드 클러스터에서 실행되는지 여부에 관계없이 개발자와 클러스터 운영자에게 일관된 경험과 기능 세트를 제공한다.

구성 요소 아키텍처(링크)

    • BGP(Border Gateway Protocol): AS 사이에서 이용되는 라우팅 프로토콜. 대규모 네트워크(수천만의 경로 수)에 대응하도록 설계됐다. 그래서 BGP로 동작하는 라우터는 비교적 고가인 제품이 많다.
    • AS(Autonomous System): 하나의 정책을 바탕으로 관리되는 네트워크(자율 시스템)를 말한다. ISP, 엔터프라이즈 기업, 공공기관 같은 조직이 이에 해당하며 인터넷은 이러한 자율 시스템의 집합체이다.여러가지 구성 요소가 많지만, 일단 눈여겨 볼 내용은 Calico가 사용하는 Datastore[1]와 마스터 노드를 포함한 모든 노드들에 존재하는 Calico Pods[2]
      • Felix (필릭스) : 인터페이스 관리, 라우팅 정보 관리, ACL 관리, 상태 체크
      • BIRD (버드): BGP Peer 에 라우팅 정보 전파 및 수신, BGP RR(Route Reflector)
      • Confd : calico global 설정과 BGP 설정 변경 시(트리거) BIRD 에 적용해줌
      • Datastore plugin : calico 설정 정보를 저장하는 곳 – k8s API datastore(kdd) 혹은 etcd 중 선택
      • Calico IPAM plugin : 클러스터 내에서 파드에 할당할 IP 대역
      • calico-kube-controllers : calico 동작 관련 감시(watch)
      • calicoctl : calico 오브젝트를 CRUD 할 수 있다, 즉 datastore 접근 가능

구성 요소 확인하기

  • 데몬셋으로 각 노드에 calico-node 파드가 동작하여, 해당 파드에 birdfelixconfd 등이 동작 + Calico 컨트롤러 파드는 디플로이먼트로 생성
    • Calico의 특징은 BGP를 이용해 각 노드에 할당된 Pod 대역의 정보를 전달한다. 즉, 쿠버네티스 서버뿐만 아니라 물리적인 라우터와도 연동이 가능 하다는 뜻이다. (Flannel의 경우 해당 구성 불가)
    • Calico Pod 안에서 Bird라고 하는 오픈소스 라우팅 데몬 프로그램이 프로세스로 동작하여 각 Node의 Pod 정보가 전파되는 것이다.
    • 이후 Felix라는 컴포넌트가 리눅스 라우터의 라우팅 테이블 및 iptables rule에 전달 받은 정보를 주입하는 형태이다.
    • confd는 변경되는 값을 계속 반영할 수 있도록 트리거 하는 역할이다.

Calico 기본 통신 과정 확인하기

calicoctl 설치

  • 리소스 관리를 위해 Calico CLI를 설치 및 구성

마스터 노드 확인

  • Calico CNI 설치시, 데몬셋이므로 모든 노드에 칼리코 파드가 하나씩 존재하게 된다. (calico-node-*)
  • 칼리코 컨트롤러가 하나 존재하는 것을 확인할 수 있다.
  • calicoctl ipm show 명령어를 통해, IAPM 정보를 확인할 수 있다. 아래 스크린샷에서는 172.16.0.0/16 대역을 해당 쿠버네티스 클러스터에서 사용할 수 있다는 내용을 알 수 있다.

    • IPAM(IP Address Management): 풍부한 사용자 환경을 통해 IP 주소 인프라의 엔드 투 엔드 계획, 배포, 관리 및 모니터링을 지원하는 통합 도구 모음이다.
      IPAM은 네트워크상의 IP 주소 인프라 서버 및 DNS(도메인 이름 시스템) 서버를 자동으로 검색하여 중앙 인터페이스에서 이들 서버를 관리할 수 있다.
    • 옵션을 통해 아래와 같이 특정한 노드에 할당 가능한 대역대를 확인할 수도 있음(Block는 각 노드에 할당된 Pod CIDR 정보를 나타냄)
  • calicoctl node 정보 확인
  • ippool 정보 확인
  • 파드와 서비스 사용 네트워크 대역 정보 확인

실습 1.

동일 노드 내 파드 간 통신

  • 결론: 동일 노드 내의 파드 간 통신은 내부에서 직접 통신됨

파드 생성 전 노드(k8s-w1)의 기본 상태

노드(k8s-w1)에 파드 2개 생성

  • 아래 내용으로 node1-pod2.yaml 파일 작성 후 파드 생성
  • 파드 생성 전후의 변화를 관찰하기 위해 터미널 하단 추가 탭에watch calicoctl get workloadEndpoint 명령어를 사용하여 모니터링
    • calicoctl 명령어로 endpoint 확인: veth 정보도 확인할 수 있음

생성된 파드 정보 확인

네트워크 인터페이스 정보 확인(k8s-w1)

  • calice#~ 두개 추가된 것을 확인할 수 있음
  • 각각 net ns 0,1로 호스트와 구별되는 것을 확인할 수 있음

네트워크 네임스페이스 확인

  • 아래 2개 PAUSE 컨테이너가 각각 파드별로 생성된 것을 확인할 수 있음
  • 바로 위 스크린샷인 link-netnsid 0, link-netnsid 1과 매칭됨

라우팅 테이블 확인

  • 파드의 IP/32bit 호스트 라우팅 대역이 라우팅 테이블에 추가된 것을 확인할 수 있음

파드간 통신 실행 이해

  • (위) 마스터 노드에서 Pod1 Shell에 접근하여 Pod2로 Ping 테스트
  • (아래) 워커 노드(k8s-w1)에서 iptables 필터 테이블에 FORWARD 리스트 중 cali-FORWARD 룰 정보를 필터링해서 watch로 확인
  • 테스트 결과 아래 이미지와 같이 Host iptables에서 FOWRARD라는 테이블의 허용 조건에 따라 정상적으로 통신이 가능한 것을 확인할 수 있다.

파드에서 외부(인터넷)로의 통신

  • 결론: 파드에서 외부(인터넷) 통신 시에는 해당 노드의 네트워크 인터페이스 IP 주소로 MASQUERADE(출발지 IP가 변경) 되어서 외부에 연결됨

파드 배포 전 calico 설정 정보 확인 & 노드에 iptables 확인

  • 마스터 노드에서 아래 내용 확인: natOutgoing의 기본값이 true로 설정되어 있는 것을 확인 할 수 있다. 즉 이 노드에서 외부로 통신할 때 NAT의 MASQUERADE를 사용하겠다는 의미이다.

    NAT – MASQUERADE : 조건에 일치하는 패킷의 출발지 주소를 변환하는 것. 내부에서 전달되는 요청의 출발지 주소를 조건에 지정된 인터페이스의 IP로 변환한다.

  • 워커 노드(k8s-w1)에서도 외부로 통신시 MASQUERADE 동작 Rule이 존재하는 것을 확인할 수 있다.

마스터 노드에서 워커 노드(k8s-w1)에 아래 내용의 파드 1개 생성

외부 통신 가능 여부 확인

  • 통신 전, 워커 노드(k8s-w1)에 iptables NAT MASQUERADE 모니터링을 활성화 하면 외부 통신시 pkts값이 증가하는지 확인할 수 있다.
  • (위) 마스터 노드에서 Pod1 Shell 실행 후, 8.8.8.8로의 통신 성공
  • (아래) pkts 값이 이전 이미지와 다르게 증가한 것을 확인할 수 있다.

다른 노드에서 파드 간 통신

  • 결론: 다른 노드 환경에서 파드 간 통신시에는 IPIP터널(기본값) 모드를 통해서 이루어진다.
    • 각 노드에 파드 네트워크 대역은 Bird에 의해서 BGP로 광고 전파/전달 되며, Felix에 의해서 호스트의 라우팅 테이블에 자동으로 추가/삭제 된다.
    • 다른 노드 간의 파드 통신은 tunl0 인터페이스를 통해 IP 헤더에 감싸져서 상대측 노드로 도달 후 tunl0 인터페이스에서 Outer 헤더를 제거하고 내부 파드와 통신한다.

파드 배포 전, 노드에서 BGP에 의해 전달 받은 정보가 호스트 라우팅 테이블에 존재하는지 확인

  • 아래 명령어를 통해 나머지 노드들의 파드 대역을 자신의 호스트 라우팅 테이블에 가지고 있고, 해당 경로는 tunl0 인터페이스로 보내게 된다는 사실을 알 수 있다.

워커 노드(k8s-w1, w2)의 tunl0 정보 확인

  • 터널 인터페이스가 IP에 할당되어 있음
  • MTU는 1480 (칼리코 사용 시 파드의 인터페이스도 기본 MTU 1480 사용)
  • 현재 TX/RX 카운트는 0 –> 잠시 후, 오버레이 통신시 카운트 값이 증가할 것

마스터 노드에서 워커 노드(k8s-w1, w2) 대상으로 각각 파드 1개씩 생성

  • calicoctl 명령어를 이용하여 생성된 파드의 엔드포인트 확인

각 노드에서 파드 간 통신을 처리하는 라우팅 정보 확인

  • k8s-w1(172.16.158.4/32) 노드에서 w2(172.16.184.0) 노드 대역에 통신하려면 192.168.10.102를 거쳐야 한다는 것을 확인할 수 있다.
  • 반대로 w2(172.16.184.1/32) 노드에서 w1(172.16.158.0) 노드 대역에 통신하려면 192.168.10.101를 거쳐야 한다.

다른 노드 파드 간 통신이 어떻게 실행되는지 확인 ⇒ IPIP

  • (상) Pod2가 속한 노드(k8s-w2)에 tunl0 인터페이스 TX/RX 패킷 카운트 모니터링 세팅
  • (중) 마스터 노드에서 Pod1 Shell 접속 후, Pod2로 Ping 통신 테스트 준비
  • (하) Pod1이 속한 노드(k8s-w1)에서 패킷 덤프 세팅: tunl0 – 터널 인터페이스에 파드간 IP 패킷 정보를 확인할 수 있음
  • 결과
    • (중) Pod1 –> Pod2로 정상 통신 확인
    • (상) tunl0 인터페이스의 TX/RX 패킷 카운트가 각각 10개로 증가
    • (하) 실제 통신을 하게 되는 파드 간 IP 패킷 정보 확인
  • 실제로 오버레이 통신을 하고 있는지 확인하기 위해 패킷덤프 명령어를 아래와 같이 수정하여 Ping 통신을 다시 하였고, 결과적으로 IP Outer(파란색 박스) 헤더 정보 안쪽에 Inner(빨간색 박스) 헤더가 1개 더 있음을 확인할 수 있다.

Calico 네트워크 모드

Calico Mode 요약

  • 칼리코는 다양한 네트워크 통신 방법을 제공한다.

IPIP 모드

  • 파드 간 통신이 노드와 노드 구간에서는 IPIP 인캡슐레이션을 통해 이루어진다.
  • 단, Azure 네트워크에서는 IPIP 통신이 불가능하기 때문에 대신 VXLAN 모드를 사용한다고 한다.

Direct 모드

  • 파드 통신 패킷이 출발지 노드의 라우팅 정보를 보고 목적지 노드로 원본 패킷 그대로 전달된다.
  • 단, 클라우드 사업자 네트워크 사용 시, NIC에 매칭되지 않는 IP 패킷은 차단되니 NIC의 Source/Destination Check 기능을 Disable해야 정상 통신 가능 (AWS 문서 링크)

BGP 연동

  • Kubernetes 클러스터 내부 네트워크와 IDC 내부망 네트워크 간 직접 라우팅도 가능

VXLAN 모드

  • 파드 간 통신이 노드와 노드 구간에서는 VXLAN 인캡슐레이션을 통해서 이루어진다.
  • 다른 노드 간의 파드 통신은 vxlan 인터페이스를 통해 L2 프레임이 UDP – VXLAN에 감싸져 상대 노드로 도달 후 vxlan 인터페이스에서 Outer헤더를 제거하고 내부의 파드와 통신하게 된다.
  • BGP 미사용, VXLAN L3 라우팅을 통해서 동작한다.
  • UDP를 사용하므로 Azure 네트워크에서도 사용 가능하다.

Pod 패킷 암호화(네트워크 레벨)

  • Calico의 다양한 네트워크 모드 환경 위에서 WireGuard 터널을 자동 생성 및 파드 트래픽을 암호화하여 노드 간 전달한다.
  • Yaml 파일에 간단하게 추가하는 것만으로도 네트워크 레벨의 패킷 암호화를 설정할 수 있다.
  • WireGuard는 구닥다리 IPsec 및 OpenVPN의 대항마로 등장한 open source VPN project이며 작년, Linux 5.6 커널에 WireGuard 1.0.0 기본 패키지로 탑재되었다.
  • 정말 간결한 코드 구조와 빠른 성능 (모든 것이 kernel에서 동작하고, 주요 암호 알고리즘에 대해서 병렬처리하므로써 빠른 속도를 자랑함)

실습 2. WireGuard

WireGuard 설정

  • 모든 노드에 WireGuard를 설치(apt install wireguard -y)하고, Enabled 설정
  • 현재 노드에 존재하는 Wireguard 퍼블릭 키 확인
  • wireguard.cali 인터페이스 정보 확인
  • wg로 시작하는 명령어를 사용하여 wireguard.cali 설정 확인: 노드 별로 각각의 상대방 Peer의 IP와 퍼블릭 키를 확인할 수 있음

동작 확인

  • 아래 내용으로 파드 생성
  • (상) 파드가 생성된 노드의 eth0(enp0s8)에서 패킷 덤프 모니터링 세팅
  • (하) 생성한 파드 Shell 접속 후 Ping 통신 준비
  • (하) Pod2 IP 확인
  • (중) Pod1 –> Pod2 Ping 정상 통신
  • (상) 51820 포트 패킷 덤프 내용 확인

[Tomcat] 리눅스의 톰캣 로그에서 한글깨지는 문제 해결방법

리눅스의 톰캣 로그에서 한글이 깨져나오네요.

톰캣의 인코딩에 문제가 생겨서 그러겠죠?

[톰캣설치 폴더 > bin] 디렉토리로 가면 catalina.sh 파일이 있습니다.

그 파일을 편집기로 여시구요.

-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
이 부분 찾아서 그 아래에 아래 소스를 모두 추가합니다.

-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
-Dfile.encoding=”utf-8″\

수정한 파일을 저장하고, 톰캣을 재시작하면 아래처럼 로그에 한글이 잘 나옵니다.

kubeadm 이용 Ubuntu 20.04에 Kubernetes 클러스터 설치

Kubernetes는 온프레미스 서버 또는 하이브리드 클라우드 환경에서 대규모로 컨테이너화된 애플리케이션을 오케스트레이션 및 관리하기 위한 도구입니다. Kubeadm은 사용자가 모범 사례 시행을 통해 프로덕션 준비 Kubernetes 클러스터를 설치할 수 있도록 Kubernetes와 함께 제공되는 도구입니다. 이 튜토리얼은 kubeadm을 사용하여 Ubuntu 20.04에 Kubernetes 클러스터를 설치하는 방법을 보여줍니다.

Kubernetes 클러스터 배포에는 두 가지 서버 유형이 사용됩니다.

  • 마스터 : Kubernetes 마스터는 Kubernetes 클러스터의 포드, 복제 컨트롤러, 서비스, 노드 및 기타 구성 요소에 대한 제어 API 호출이 실행되는 곳입니다.
  • Node : Node는 컨테이너에 런타임 환경을 제공하는 시스템입니다. 컨테이너 포드 세트는 여러 노드에 걸쳐 있을 수 있습니다.

실행 가능한 설정을 위한 최소 요구 사항은 다음과 같습니다.

  • 메모리: 컴퓨터당 2GiB 이상의 RAM
  • CPU: 컨트롤 플레인 머신에 최소 2개의 CPU 가 있습니다.
  • 컨테이너 풀링을 위한 인터넷 연결 필요(개인 레지스트리도 사용할 수 있음)
  • 클러스터의 머신 간 전체 네트워크 연결 – 개인 또는 공용입니다.

Ubuntu 20.04에 Kubernetes 클러스터 설치

My Lab 설정에는 3개의 서버가 있습니다. 컨테이너화된 워크로드를 실행하는 데 사용할 하나의 컨트롤 플레인 머신과 두 개의 노드. 예를 들어 HA용 제어 평면 노드 3개 를 사용하여 원하는 사용 사례 및 부하에 맞게 노드를 더 추가할 수 있습니다 .

서버 유형 서버 호스트 이름 명세서
주인 k8s-master01.computingforgeeks.com 4GB 램, 2vcpus
노동자 k8s-worker01.computingforgeeks.com 4GB 램, 2vcpus
노동자 k8s-worker02.computingforgeeks.com 4GB 램, 2vcpus

1단계: Kubernetes 서버 설치

Ubuntu 20.04에서 Kubernetes 배포에 사용할 서버를 프로비저닝합니다. 설정 프로세스는 사용 중인 가상화 또는 클라우드 환경에 따라 다릅니다.

서버가 준비되면 업데이트하십시오.

sudo apt update
sudo apt -y upgrade && sudo systemctl reboot

2단계: kubelet, beadm 및 kubectl 설치

서버가 재부팅되면 Ubuntu 20.04용 Kubernetes 저장소를 모든 서버에 추가하십시오.

sudo apt update
sudo apt -y install curl apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

그런 다음 필요한 패키지를 설치합니다.

sudo apt update
sudo apt -y install vim git curl wget kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

kubectl 버전을 확인하여 설치를 확인합니다.

$ kubectl version --client && kubeadm version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:38:50Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}
kubeadm version: &version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:37:34Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}

3단계: 스왑 비활성화

스왑과 방화벽을 끕니다.

sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
sudo swapoff -a
sudo ufw disable

crontab -e
@reboot sudo swapoff -a 

커널 모듈을 활성화하고 sysctl을 구성합니다.

# Enable kernel modules
sudo modprobe overlay
sudo modprobe br_netfilter

# Add some settings to sysctl
sudo tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# Reload sysctl
sudo sysctl --system

4단계: 컨테이너 런타임 설치

Pod에서 컨테이너를 실행하기 위해 Kubernetes는 컨테이너 런타임을 사용합니다. 지원되는 컨테이너 런타임은 다음과 같습니다.

  • 도커
  • CRI-O
  • 컨테이너

참고 : 한 번에 하나의 런타임을 선택해야 합니다 .

도커 런타임 설치:

# Add repo and Install packages
sudo apt update
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

sudo apt update
sudo apt install -y containerd.io docker-ce docker-ce-cli

# Create required directories
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo mkdir -p /etc/docker

# Create daemon json config file
sudo tee /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

# Start and enable Services
sudo systemctl daemon-reload 
sudo systemctl restart docker
sudo systemctl enable docker

CRI-O 설치:

# Ensure you load modules
sudo modprobe overlay
sudo modprobe br_netfilter

# Set up required sysctl params
sudo tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# Reload sysctl
sudo sysctl --system

# Add Cri-o repo
sudo su -
OS="xUbuntu_20.04"
VERSION=1.22
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

# Update CRI-O CIDR subnet
sudo sed -i 's/10.85.0.0/192.168.0.0/g' /etc/cni/net.d/100-crio-bridge.conf

# Install CRI-O
sudo apt update
sudo apt install cri-o cri-o-runc

# Start and enable Service
sudo systemctl daemon-reload
sudo systemctl restart crio
sudo systemctl enable crio
sudo systemctl status crio

컨테이너 설치:

# Configure persistent loading of modules
sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

# Load at runtime
sudo modprobe overlay
sudo modprobe br_netfilter

# Ensure sysctl params are set
sudo tee /etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# Reload configs
sudo sysctl --system

# Install required packages
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates

# Add Docker repo
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# Install containerd
sudo apt update
sudo apt install -y containerd.io

# Configure containerd and start service
sudo su -
mkdir -p /etc/containerd
containerd config default>/etc/containerd/config.toml

# restart containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
systemctl status  containerd

 cgroup 드라이버 설치

systemd cgroup 드라이버를 사용하려면 에서 plugins.cri.systemd_cgroup = true 를 설정 /etc/containerd/config.toml하십시오. kubeadm을 사용할 때 kubelet 용 cgroup 드라이버를 수동으로 구성하십시오.

5단계: 마스터 노드 초기화

마스터로 사용할 서버에 로그인하고 br_netfilter 모듈이 로드되었는지 확인합니다.

$ lsmod | grep br_netfilter
br_netfilter           22256  0 
bridge                151336  2 br_netfilter,ebtable_broute

컨테이너 이미지 가져오기:

$ sudo kubeadm config images pull
[config/images] Pulled k8s.gcr.io/kube-apiserver:v1.22.2
[config/images] Pulled k8s.gcr.io/kube-controller-manager:v1.22.2
[config/images] Pulled k8s.gcr.io/kube-scheduler:v1.22.2
[config/images] Pulled k8s.gcr.io/kube-proxy:v1.22.2
[config/images] Pulled k8s.gcr.io/pause:3.5
[config/images] Pulled k8s.gcr.io/etcd:3.5.0-0
[config/images] Pulled k8s.gcr.io/coredns/coredns:v1.8.4

kubelet 서비스를 활성화합니다.

sudo systemctl enable kubelet

이제 etcd (클러스터 데이터베이스)와 API 서버를 포함하는 컨트롤 플레인 구성 요소를 실행할 시스템을 초기화하려고 합니다.

 

CRI 소켓이 여러 개인 경우 다음 --cri-socket중 하나를 선택 하는 데 사용하십시오.

# CRI-O
sudo kubeadm config images pull --cri-socket /var/run/crio/crio.sock

# Containerd
sudo kubeadm config images pull --cri-socket /run/containerd/containerd.sock

# Docker
sudo kubeadm config images pull --cri-socket /var/run/dockershim.sock

kubeadm init클러스터를 부트스트랩하는 데 사용되는 기본 옵션입니다.

--control-plane-endpoint : 모든 제어 평면 노드에 대한 공유 끝점을 설정합니다. DNS/IP일 수 있음
 --pod-network-cidr : 포드 네트워크 추가 기능을 설정하는 데 사용됨 CIDR
 --cri-socket : 런타임 소켓 경로를 설정하기 위해 컨테이너 런타임이 둘 이상인 경우 사용
 --apiserver-advertise-address : 이 특정 제어 평면 노드의 API 서버에 대한 광고 주소 설정

공유 엔드포인트가 없는 부트스트랩 (Worker 초기 설정 시 진행)

DNS 엔드포인트를 사용하지 않고 클러스터를 부트스트랩하려면 다음을 실행합니다.

sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16

공유 엔드포인트가 있는 부트스트랩(제어 평면 API의 DNS 이름)

클러스터 엔드포인트 DNS 이름을 설정하거나 /etc/hosts 파일에 레코드를 추가합니다.

$ sudo vim /etc/hosts
172.29.20.5 k8s-cluster.computingforgeeks.com

클러스터 생성: (Master Node 경우)

sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

참고 : 192.168.0.0/16 이 이미 네트워크 내에서 사용 중인 경우 위 명령에서 192.168.0.0/16을 대체하여 다른 포드 네트워크 CIDR을 선택해야 합니다.

컨테이너 런타임 소켓:

실행 시간 Unix 도메인 소켓 경로
도커 /var/run/docker.sock
용기에 담긴 /run/containerd/containerd.sock
만들기 /var/run/crio/crio.sock

선택적으로 런타임용 소켓 파일을 전달하고 설정에 따라 주소를 알릴 수 있습니다.

# CRI-O
sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --cri-socket /var/run/crio/crio.sock \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

# Containerd
sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --cri-socket /run/containerd/containerd.sock \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

# Docker
sudo kubeadm init \
  --pod-network-cidr=192.168.0.0/16 \
  --cri-socket /var/run/docker.sock \
  --upload-certs \
  --control-plane-endpoint=k8s-cluster.computingforgeeks.com

다음은 초기화 명령의 출력입니다.

....
[init] Using Kubernetes version: v1.22.2
[preflight] Running pre-flight checks
	[WARNING Firewalld]: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Using existing ca certificate authority
[certs] Using existing apiserver certificate and key on disk
[certs] Using existing apiserver-kubelet-client certificate and key on disk
[certs] Using existing front-proxy-ca certificate authority
[certs] Using existing front-proxy-client certificate and key on disk
[certs] Using existing etcd/ca certificate authority
[certs] Using existing etcd/server certificate and key on disk
[certs] Using existing etcd/peer certificate and key on disk
[certs] Using existing etcd/healthcheck-client certificate and key on disk
[certs] Using existing apiserver-etcd-client certificate and key on disk
[certs] Using the existing "sa" key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/admin.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Using existing kubeconfig file: "/etc/kubernetes/scheduler.conf"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
W0611 22:34:23.276374    4726 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[control-plane] Creating static Pod manifest for "kube-scheduler"
W0611 22:34:23.278380    4726 manifests.go:225] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 8.008181 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.21" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-master01.computingforgeeks.com as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master01.computingforgeeks.com as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: zoy8cq.6v349sx9ass8dzyj
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join k8s-cluster.computingforgeeks.com:6443 --token sr4l2l.2kvot0pfalh5o4ik \
    --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18 \
    --control-plane 

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join k8s-cluster.computingforgeeks.com:6443 --token sr4l2l.2kvot0pfalh5o4ik \
    --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18

출력의 명령을 사용하여 kubectl을 구성합니다.

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

echo 'export KUBECONFIG=$HOME/.kube/config' >> $HOME/.bashrc

클러스터 상태 확인:

$ kubectl cluster-info
Kubernetes master is running at https://k8s-cluster.computingforgeeks.com:6443
KubeDNS is running at https://k8s-cluster.computingforgeeks.com:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

설치 출력의 명령을 사용하여 마스터 노드를 추가할 수 있습니다.

kubeadm join k8s-cluster.computingforgeeks.com:6443 --token sr4l2l.2kvot0pfalh5o4ik \
    --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18 \
    --control-plane 

6단계: 마스터에 네트워크 플러그인 설치

이 가이드에서는 Calico 를 사용 합니다. 지원되는 다른 네트워크 플러그인 을 선택할 수 있습니다 .

kubectl create -f https://docs.projectcalico.org/manifests/tigera-operator.yaml 
kubectl create -f https://docs.projectcalico.org/manifests/custom-resources.yaml

다음 출력이 표시되어야 합니다.

customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/apiservers.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/imagesets.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/installations.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/tigerastatuses.operator.tigera.io created
namespace/tigera-operator created
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/tigera-operator created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created
.....
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created

모든 포드가 실행 중인지 확인합니다.

$ watch kubectl get pods --all-namespaces
NAMESPACE     NAME                                                         READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-76d4774d89-nfqrr                     1/1     Running   0          2m52s
kube-system   calico-node-kpprr                                            1/1     Running   0          2m52s
kube-system   coredns-66bff467f8-9bxgm                                     1/1     Running   0          7m43s
kube-system   coredns-66bff467f8-jgwln                                     1/1     Running   0          7m43s
kube-system   etcd-k8s-master01.computingforgeeks.com                      1/1     Running   0          7m58s
kube-system   kube-apiserver-k8s-master01.computingforgeeks.com            1/1     Running   0          7m58s
kube-system   kube-controller-manager-k8s-master01.computingforgeeks.com   1/1     Running   0          7m58s
kube-system   kube-proxy-bt7ff                                             1/1     Running   0          7m43s
kube-system   kube-scheduler-k8s-master01.computingforgeeks.com            1/1     Running   0          7m58s

마스터 노드가 준비되었는지 확인합니다.

# CRI-O
$ kubectl get nodes -o wide
NAME     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu   Ready    control-plane,master   38s   v1.22.2   143.198.114.46   <none>        Ubuntu 20.04.3 LTS   5.4.0-88-generic   cri-o://1.22.0

# Containerd
$ kubectl get nodes -o wide
NAME     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ubuntu   Ready    control-plane,master   15m   v1.22.2   143.198.114.46   <none>        Ubuntu 20.04.3 LTS   5.4.0-88-generic   containerd://1.4.11

# Docker
$ kubectl get nodes -o wide
NAME           STATUS   ROLES    AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
k8s-master01   Ready    master   64m   v1.22.2   135.181.28.113   <none>        Ubuntu 20.04 LTS   5.4.0-37-generic   docker://20.10.8

7단계: 작업자 노드 추가

제어 플레인이 준비되면 예약된 워크로드를 실행하기 위해 클러스터에 작업자 노드를 추가할 수 있습니다.

엔드포인트 주소가 DNS에 없으면 /etc/hosts 에 레코드를 추가 합니다 .

$ sudo vim /etc/hosts
172.29.20.5 k8s-cluster.computingforgeeks.com

주어진 조인 명령은 클러스터에 작업자 노드를 추가하는 데 사용됩니다.

kubeadm join k8s-cluster.computingforgeeks.com:6443 \
  --token sr4l2l.2kvot0pfalh5o4ik \
  --discovery-token-ca-cert-hash sha256:c692fb047e15883b575bd6710779dc2c5af8073f7cab460abd181fd3ddb29a18

산출:

[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.21" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

제어 플레인에서 아래 명령을 실행하여 노드가 클러스터에 합류했는지 확인합니다.

$ kubectl get nodes
NAME                                 STATUS   ROLES    AGE   VERSION
k8s-master01.computingforgeeks.com   Ready    master   10m   v1.22.2
k8s-worker01.computingforgeeks.com   Ready    <none>   50s   v1.22.2
k8s-worker02.computingforgeeks.com   Ready    <none>   12s   v1.22.2

$ kubectl get nodes -o wide

조인 토큰이 만료된 경우 작업자 노드에 조인하는 방법에 대한 가이드를 참조하십시오.

8단계: 클러스터에 애플리케이션 배포

단일 노드 클러스터만 있는 경우 마스터 노드에서 컨테이너 포드를 실행하는 방법에 대한 가이드를 확인하세요.

애플리케이션을 배포하여 클러스터가 작동하는지 확인해야 합니다.

kubectl apply -f https://k8s.io/examples/pods/commands.yaml

포드가 시작되었는지 확인

$ kubectl get pods
NAME           READY   STATUS      RESTARTS   AGE
command-demo   0/1     Completed   0          16s

9단계: Kubernetes 대시보드 설치(선택 사항)

Kubernetes 대시보드는 컨테이너화된 애플리케이션을 Kubernetes 클러스터에 배포하고, 컨테이너화된 애플리케이션의 문제를 해결하고, 클러스터 리소스를 관리하는 데 사용할 수 있습니다.

설치 가이드를 참조하십시오: NodePort로 Kubernetes 대시보드를 설치하는 방법

10단계: Metrics Server 설치(Pod 및 노드 리소스 사용량 확인용)

Metrics Server  는 리소스 사용량 데이터의 클러스터 전체 집계 도구입니다.  각 노드에서 Kubelet 에 의해 노출된  요약 API 에서 메트릭을 수집  합니다. 아래 가이드를 사용하여 배포하세요.

11단계: Prometheus/Grafana 모니터링 배포

Prometheus는 Kubernetes 클러스터의 고급 메트릭 기능에 액세스할 수 있는 완전한 솔루션입니다. Grafana는 Prometheus 데이터베이스에 수집 및 저장되는 메트릭의 분석 및 대화형 시각화에 사용됩니다. Kubernetes 클러스터에서 전체 모니터링 스택을 설정하는 방법에 대한 완전한 가이드가 있습니다.

12단계: 영구 저장소 구성 아이디어(선택 사항)

Kubernetes용 영구 스토리지 솔루션도 찾고 있다면 다음을 확인하십시오.

13. Nginx 인그레스 컨트롤러 설치

Nginx가 Kubernetes 워크로드용으로 선호하는 Ingress 컨트롤러인 경우 설치 프로세스에 대한 가이드를 사용할 수 있습니다.

더 많은 가이드:

유사한 Kubernetes 배포 가이드:

VirtualBox에 VMware ESXi 설치 방법

중요:  IntelCPU를 소유하고 있는 경우VirtualBox에서실행되는 VM ESXi 호스트에서 새 VM 시스템을 시작할 수 없다는점에 유의하십시오. 

이것은 VirtualBox가 Intel CPU에 대한 중첩 가상화를 지원하지 않기 때문에 발생합니다. 

(VM 머신을 시작하려고 하면 “이 호스트는 Intel VT-x를 지원하지 않습니다.”라는 오류가 표시됩니다.) 따라서 Intel CPU를 소유하고 있다면VMware 플레이어에 ESXi설치하는것이 좋습니다.

VirtualBox에 ESXi vSphere Hypervisor를 설치하기 위한 하드웨어 요구 사항:

CPU: 호스트 시스템에는 최소 2개의 CPU 코어가 있어야 하고 CPU는 하드웨어 가상화 기능(Intel VT-x 또는 AMD RVI)을 지원해야 합니다. 시스템이 가상화를 지원하는지 확인하려면 CPUID CPU-Z 유틸리티를사용하십시오. *

* 참고:
1. 가상화 지원을 활성화하려면 BIOS 설정으로 이동 하여 Intel-VD(Intel VT-x) 또는 AMD VT 기술/기능을 활성화 합니다 .

RAM: ESXi에는 최소 2GB의 물리적 RAM이 필요합니다. VirtualBox에 ESXi를 설치하려면 최소 4GB(4096MB)의 RAM을 할당해야 합니다.

VirtualBox에 ESXi vSphere Hypervisor 6.7을 설치하기 위한 소프트웨어 요구 사항.

1. 이동 링크 및 작성 VM웨어 계정을 (당신이 이미 하나를 가지고 있지 않은 경우).
2. VMware vSphere Hypervisor(ESXi ISO) 이미지(VMware 도구 포함) 이미지를 다운로드 합니다 .

3. 평가판 라이센스(60일)를 무료(만료되지 않음)로 변환하려면 평가판 기간이 끝날 때 필요하므로 VMware vSphere Hypervisor 6 라이센스 키를 기록해 둡니다 . (기사의 끝을 참조하십시오).

4. VirtualBox에 ESXi VSphere Hypervisor를 설치하려면 여기 에서 Windows 호스트용 Virtualbox의 최신 릴리스를 다운로드하여 설치해야 합니다 .

영상

VirtualBox 호스트에 VMware vSphere Hypervisor(ESXi 서버)를 설치하는 방법.

1단계. ESXI용 가상 머신 생성 및 구성 *

1.   Oracle VM Virtual Box Manager를 시작하고 새로 만들기 를 클릭 합니다 .

vmware esxi 설치 virtualbox

2. 가상 머신의 이름(예: “eSXI vSphere”)을 지정하고 다음을 선택합니다.

유형: 리눅스

버전: Linux 2.6/3.x/4.x(64비트)

메모리 크기: 4096MB

하드 디스크: 지금 가상 디스크 만들기

3. 완료되면 만들기를 클릭 합니다.

VirtualBox에 VMware ESXi 6.7을 설치하는 방법.

4. 다음 화면에서 원하는 디스크 크기(예: 30GB)를 지정하고 ‘하드 디스크 파일 유형’: VDI(VirtualBox 디스크 이미지) 및 ‘실제 하드 디스크에 저장’: 동적 할당 의 기본 옵션을 그대로 두고 클릭합니다. 생성 .

VirtualBox에 ESXi 설치

5. 이제 새 가상 머신을 강조 표시하고 설정 을 클릭 합니다 .

영상

6a. 왼쪽에서 시스템 을 선택 하고 마더보드 탭에서 다음을 선택합니다.

  • 칩셋: ICH9
  • 포인팅 장치: PS/2 마우스

영상

6b. 그런 다음 프로세서 탭을 선택 하고…

  • 2개의   CPU를 할당합니다 .
  • PAE/NX 활성화 확인

영상

7. 그런 다음 스토리지를 선택 하고 광학 드라이브 추가  기호 를 클릭합니다 .

영상

8. 디스크 선택 을 선택한 다음 다운로드한 ‘vSphere Hypervisor(ESXi ISO)’ 파일을 선택합니다.

영상

9a. 마지막으로 네트워크 를 선택하고 호스트 전용 어댑터 를 선택한 다음 확인 을 클릭 합니다.

영상

9b. 마법사 기반 생성 프로세스 후에 가상화 기술을 실행할 수 있도록 생성된 VM을 수정해야 합니다.

이는 CLI(PowerShell/CMD)를 통해서만 가능합니다.

cd 'C:\Program Files\Oracle\VirtualBox\'
.\VBoxManage.exe modifyvm "VMwareESXi" --nested-hw-virt on

 

10. 시작 버튼을 클릭하고 아래로 진행하여 가상 머신에 ESXi vSphere Hypervisor를 설치합니다.

영상

2단계. VIRTUALBOX VM 머신에 VMWARE ESXI VSPHERE HYPERVISOR 6.7을 설치합니다.

* 참고: 물리적 시스템에 ESXi vSphere Hypervisor를 설치하는 경우 ESXi vSphere Hypervisor 설치 CD 미디어에서 시스템을 부팅하십시오.

1. 첫 화면에서 Enter 를 눌러 설치를 시작합니다.

VirtualBox 호스트에 ESXi vSphere Hypervisor를 설치하는 방법

2. VMware ESXI 설치 프로그램이 시작되어야 합니다…

영상

3. 시작 화면에서 Enter 키 를 누릅니다 .

영상

4. F11 키 를 눌러 사용권 계약에 동의합니다.

영상

5. 스토리지 옵션에서 Enter 키를 누릅니다 .

영상

6. 원하는 키보드 레이아웃을 선택하거나 기본값(미국)을 그대로 두고 Enter 키를 누릅니다 .

영상

7. 이제 원하는 비밀번호*를 두 번 입력 하고 Enter 키를 누릅니다 .

* 참고: 비밀번호는 최소 7자 이상이어야 하며 일반 및 대문자, 기호 및 숫자의 조합이어야 합니다.

영상

8. 마지막으로 F11 키 를 눌러 설치를 중단합니다. *

* VirtualBox 설치 참고 사항: ESXi 설치 시점에서 Intel 프로세서를 소유하고 있는 경우 화면에 다음 경고 메시지가 표시됩니다. “하드웨어 가상화 경고: 하드웨어 가상화는 이 CPU의 기능이 아니거나 BIOS에서 활성화되지 않았습니다.” 이 메시지를 무시하고 Enter 키를 눌러 계속하십시오. (이 기사의 시작 부분에서 말했듯이 VirtualBox는 Intel 프로세서에 대한 중첩 가상화를 지원하지 않기 때문에 이 메시지가 나타납니다.)

영상

9. 설치가 완료되면 설치 미디어를 제거하고 Enter 키 를 눌러 시스템을 재부팅합니다. *

영상

* 참고: VirtualBox에서 ESXi 설치 미디어(.ISO 파일)를 제거하려면 

  A.재부팅 후 VM 창을 닫고컴퓨터의 전원을 끕니다 .

영상

B. 그런 다음 VM 머신 스토리지 설정을 열고 ISO 파일을 제거한 다음 확인을 클릭 합니다.
C. 마지막으로 시작 버튼을 클릭하여 VMware ESXi 머신을 시작합니다.

영상

10. VMware ESXi 서버가 시작되면 DHCP에서 할당된 IP 주소를 “가져옵니다”. 아래 지침에 따라 ESXi 서버에 이 IP 주소를 사용하거나 새 고정 IP 주소를 설정할 수 있습니다.

영상

11. ESXi에서 IP 주소를 변경하려면 위 화면에서 F2 를 누른다 .
12. 루트 암호를 입력하고 Enter 키를 누릅니다.
13. 화살표 키를 사용하여 관리 네트워크 구성으로 이동 하고 Enter 키 를 누릅니다 .

image_thumb[1]_thumb[2]

14. IPv4 구성으로 이동 하고 Enter 키를 누릅니다 .

 image_thumb[3]_thumb[3]

(15) 로 이동 한 세트 정적 IPv4 주소 및 네트워크 구성 및 히트 공간 을 선택할 수 있습니다.
16. 고정 IP 주소, 서브넷 마스크 및 게이트웨이를 입력 하고 Enter 키를 누릅니다 .

image_thumb[5]_thumb[3]

17. 그런 다음 선택 DNS 구성 및 히트 입력합니다 .

image_thumb[7]_thumb[3]

18. 이동 정보는 다음의 제품에 다음 DNS 서버 주소 및 호스트 이름을 사용 하고 공격 공간 을 선택할 수 있습니다.
19. 유형 DNS 서버 주소 및 선택적으로 다른 호스트 이름을 지정합니다. 완료되면 Enter 키를 누릅니다 .

image_thumb[9]_thumb[1]

20. ESC 를 눌러 종료한 다음 Y 를 눌러 변경 사항을 적용하고 관리 네트워크를 다시 시작합니다.

image_thumb[11]_thumb[1]

(21) 이어서 프레스 ESC 로그 아웃 한 후 프레스 F12 및 종료 ESXi 서버.
22. VirtualBox Manager에서 새 가상 머신을 강조 표시하고 설정 을 클릭 합니다 .

영상

(23) 에서 네트워크 : 옵션에 첨부를 선택 브리지 어댑터를 클릭하고 OK

영상

24. VM ESXi 머신을 시작합니다.
25. ESXi 서버가 시작되면 웹 브라우저(호스트 컴퓨터에서)를 열고 ESXi 서버의 IP 주소로 이동하여 VMWare ESXi vShere 서버 관리를 시작합니다.

영상

추가 도움말: VMware ESXi Hypervisor 평가 라이센스를 무료로 변환하려면.

* 참고: 60일 동안(평가 기간 종료 시까지) ESXi의 모든 기능을 탐색하고 테스트할 수 있습니다. 따라서 평가 기간이 종료되기 전에 평가 라이센스를 무료로 변환하지 마십시오.

1. 관리 -> 라이선스로 이동 한 다음 라이선스 할당 을 클릭 합니다 .

image_thumb17_thumb[2]

2. vSphere Hypervisor 6 라이센스 키를 복사하여 붙여넣은 다음 라이센스 확인 을 클릭합니다.

image_thumb15_thumb

3. 마지막으로 라이선스 할당을 클릭 합니다.

image_thumb16_thumb[1]

4. 이제 ‘만료 날짜’ 상태가 “Never”인 화면이 표시되어야 합니다.

image_thumb18_thumb[2]

그게 다야!

시놀로지 NAS의 OpenVPN 서버 설정하기

Synology NAS의 PPTP VPN 서버 설정 방법을 이전 포스트에서 설명했는데 한가지 설명을 빠트렸었다. 무엇인고 하니 설명한 환경에서 NAS를 SuperDMZ 또는 DMZ(NAT) 기능을 이용해 집의 인터넷 공유기에 할당되는 공인IP를 통채로 NAS에 할당한 경우에만 가능한 방법이다.

그렇지 않고 통신사에 연결되는 인터넷 공유기에는 공인IP가 할당되고 NAS에는 192.X.X.X로 표시되는 사설IP가 할당될 경우에는 PPTP, IPSEC 등의 VPN은 정상동작시키기 쉽지 않다. 인터넷 공유기에서 포트포워딩을 해줘야할 포트도 여러개인데다 설정을 하더라도 제대로 동작하지 않는 경우가 많기 때문이다.

그래서 오늘은 하나의 포트만 포트포워딩 하면 사용할 수 있는 OpenVPN 서버의 설정방법을 포스팅한다.

1. 인터넷 공유기에서 OpenVPN에서 사용할 통신포트를 포트포워딩 하기

통신사에서 제공하는 인터넷 공유기의 경우 다음과 같이 “포트포워딩(Port Forwarding)” 기능을 제공하는 경우가 대부분이다.

2. 시놀로지 NAS에서 새 인증서 만들기

많은 시놀로지 사용자들이 OpenVPN 서버를 설정하면서 부닥치는 가장 큰 난관은 바로 인증서 설정과 관련된 부분이다. 일단 “인증서”가 뭔지 제대로 이해를 하지 못하고 있기 때문이다.

(기존의 기본 인증서로 설정해도 관계 없다. 생성하는 과정만 건너 뛰면 모든 작업은 동일하다.)

먼저 “제어판”에서 “보안” 메뉴를 선택하면 표시되는 “인증서” 탭을 선택한다.

 

synology nas의 Certificate tab
Synology NAS의 제어판-보안 메뉴의 인증서 탭

 

“추가” 버튼을 누르고 “인증서 생성” 창이 실행되면 “새 인증서 추가” 를 선택한 다음 “다음” 버튼을 누른다.

“설명” 에는 적당한 설명을 넣는다. 그리고 “자체 서명 인증서 생성”을 선택한다.

 

synology nas에서 self-sign certificate 만들기
자체 서명 인증서 생성

 

다음과 같이 루트(CA) 인증서 생성에 필요한 기본값을 입력한다. 대충 입력해도 된다.

 

시놀로지 NAS의 셀프사인 인증서 생성
루트 인증서(CA) 생성

 

루트(CA) 인증서를 만들 정보를 입력하고 나면 실제 통신 시 사용할 인증서를 만들게 된다. 입력하는 정보가 아주 조금 다른데… 대충~ 에러가 나지 않도록만 입력하면 된다.

 

시놀로지 NAS에 인증서 만들기

 

“적용” 버튼을 누르면 다음과 같이 인증서가 반들어진다. 그리고 인증서의 유효기간은 생성한 날로부터 1년이다.

 

Synology NAS에 만들어진 Self-sign Certificate
Synology NAS에 만들어진 자체 서명 인증서

 

3. VPN 서버가 새로 만든 인증서를 사용하도록 설정하기

“제어판” – “보안” – “인증서” 탭에서 “구성” 버튼을 누르면 인증서를 사용하는 서비스가 사용할 인증서를 선택할 수 있는 화면이 표시된다.

아래 화면처럼 “VPN Server”가 앞에서 새로 생성한 인증서를 사용하도록 선택해준다.

 

VPN Server가 사용할 인증서 선택하기

 

4. OpenVPN 서버 설정하기

이제 OpenVPN 서버를 설정해줘야 한다.  VPN Server를 설정하기 위해서 VPN Server를 실행하고 “OpenVPN” 메뉴를 선택한다.

그리고 “OpenVPN 서버 활성화”를 체크해준 뒤 다음과 같이 설정한다.

 

 Synology NAS의 OpenVPN Server
Synology NAS의 OpenVPN 서버

 

여기서 중요한 것은 “포트” 항목에 앞의 인터넷 공유기에서 NAS의 IP인 192.168.219.102의 포트포워딩 포트인 10472를 “포트” 항목에 입력하는 것이다.

그리고 나서 “적용” 버튼을 눌러 OpenVPN 서버를 실행한다.

 

OpenVPN 서버 실행

 

OpenVPN 서버를 실행하면 화면 아래에 보이는 “내보내기 구성” 버튼이 활성화된다.

이 버튼을 눌러 OpenVPN 클라이언트에서 OpenVPN 서버에 접속할 때 사용할 “설정 파일”을 저장한다.

 

OpenVPN 설정 내보내기

 

이 OpenVPN 접속 설정 파일을 적당한 이름으로 저장한다. 위에서는 synology-openvpn(10472).zip 파일로 저장했다. 그리고 하나의 파일을 더 저장해야 한다. 바로 인증서 파일이다.

5. 인증서를 파일로 저장하기

다시 인증서 화면으로 간 뒤 아래 화면처럼 새로 생성한 인증서 파일을 “인증서 내보내기” 버튼을 눌러 PC에 저장한다.

 

Synology NAS의 인증서 내보내기

 

인증서 파일은 기본적으로 archive.zip 파일로 저장된다.

지금가지 두개의 파일을 PC에 저장했다. OpenVPN 클라이언트에서 사용할 접속 설정 파일과 인증서 파일 두 개다. 이제 이 두개 파일의 압축을 해제한 뒤 편집해야 한다.

6. OpenVPN 클라이언트 구성 파일 편집

Synology에서 제공하는 VPN 서버의 버그인지… 아니면 원래 그런 것인지 모르겠지만 앞에서 다운로드 받은 OpenVPN 클라이언트 접속 용 구성 파일은 인증서 정보가 제대로 설정되어 다운로드 되지 않는다. 그래서 수동으로 인증서 내용을 편집해 넣어줘야 한다.

먼저 다음과 같이 인증서가 저장된 archive.zip과 OpenVPN 접속 설정파일인 synology-open….zip 파일의 압축을 해제한다.

 

인증서 파일과 OpenVPN 접속 구성파일 압축해제

 

인증서 압축파일을 해제하면 4개의 파일이 표시되는데 cert.pem 파일과 prikey.pem 파일의 내용을 OpenVPN 접속 구성 파일에 추가해줘야 한다.

 

인증서 압축파일 해제하면 표시되는 4개의 파일

 

OpenVPN 접속 구성 파일이 포함된 zip 파일을 압축해제하면 VPNConfig.ovpn 이라는 OpenVPN 접속 용 구성파일이 보인다. 이 파일을 Notepad 등으로 열어준다.

 

OpenVPN 접속 용 구성파일 열기

 

먼저 상단에 위치한 YOUR_SERVER_IP를 인터넷 공유기에 할당된 외부 공인IP로 수정한다. 만약 시놀로지의 DDNS를 이용해 xxx.synology.me 와 같은 도메인주소를 사용한다면 그 도메인주소를 입력해주면 된다.

 

ovpn파일 편집하기

 

다음은 새로운 Notepad을 열어 인증서 파일들 중 cert.pem 파일을 다음과 같이 연다.

 

cert.pem
cert.pem 파일

 

위의 cert.pem 파일의 내용 전체를 다음과 같이 VPNConfig.ovpn 파일을 열고 가장 아래부분의 </ca> 뒷 부분에 <cert> 태그를 추가하고 그 뒤에 붙여넣는다.

 

.ovpn 파일의 가장 뒤에 cert.pem 파일의 내용을 붙여 넣는다.

 

그리고 가장 뒷 부분에 </cert>을 추가한다.

마찬가지로 인증서 파일들 중 prikey.pem 파일의 내용을 모두 복사해 VPNConfig.ovpn 파일의 맨 뒷 부분에 <key> 태그를 추가한 뒤 붙여넣는다.

 

.ovpn 파일의 끝에 prikey.pem 파일의 내용을 추가한다.

 

그리고 맨 끝에 </key>를 추가해준 뒤 저장한다.

여기까지 진행하면 OpenVPN 클라이언트 프로그램이 OpenVPN 서버에 접속할 때 사용할 구성파일이 완성된다.

7. OpenVPN Client 설치하고 접속 구성 파일 복사하기

OpenVPN 서버에 접속하여 암호화 된 안전한 Private(사설) 네트워크를 만들기 위해서는 OpenVPN GUI라는 클라이언트 프로그램을 설치하여야 한다. 다운로드는 여기에서 받으면 된다.

기본 옵션으로 설치한 뒤 앞에서 편집한 VPNConfig.ovpn 파일을 아래와 같이 기본 config 경로에 복사한다.

 

.ovpn 파일 복사하기

 

이 때 관리자권한이 필요한데 관리자 권한을 부여하여 복사해 넣으면 된다.

8. OpenVPN 서버에 OpenVPN GUI로 접속하기

설치하고 나면 VPNConfig 라는 접속 구성이 보인다. 아래와 같이 “연결”을 눌러 OpenVPN 서버에 접속하면 된다.

 

OpenVPN GUI를 통해 접속하기

 

ID와 비밀번호를 묻는 창이 실행되면 시놀로지의 접소계정을 입력하면 된다. 다만 해당 계정은 시놀로지 DSM에서 OpenVPN 접속이 허용된 계정이어야 한다.

 

OpenVPN 서버에 접속하기
시롤로지 OpenVPN 서버에 접속하기

 

접속이 되면 다음과 같이 접속상태를 확인할 수 있고 “연결해제” 버튼을 눌러 VPN 네트워크를 파괴하여 접속을 끊을 수도 있다.

 

Synology NAS 오픈VPN 접속 상태

DNS TXT Record 로 Let’s Encrypt SSL 인증서 발급 받기

TXT 레코드 요청

  1. certbot 을 실행할 때 –manual 옵션과 –preferred-challenges dns 을 주어서 실행합니다.
    certbot certonly -d new.lesstif.com --manual --preferred-challenges dns
  2. IP 로깅을 허용하겠냐고 묻는 화면에서 Y 를 입력합니다.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NOTE: The IP of this machine will be publicly logged as having requested this
    certificate. If you're running certbot in manual mode on a machine that is not
    your server, please ensure you're okay with that.
    
    Are you OK with your IP being logged?
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: Y
  3. TXT 에 등록할 내용이 출력되면 복사해 둡니다.
    Please deploy a DNS TXT record under the name
    _acme-challenge.new.lesstif.com with the following value:
    
    slqQSBrs4rToROM7LyEeBVvI92YXi3JJ-RK6S5OBKNc
    
    Before continuing, verify the record is deployed.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Press Enter to Continue
  4.  DNS 서버에 TXT 레코드를 등록합니다. DNS 서비스 제공자에 따라 화면이 다를 수 있습니다.
  5. 새로운 터미널을 열고 정상적으로 등록됐는지 확인합니다.
    $ nslookup -q=TXT _acme-challenge.new.lesstif.com
    
    
    Server:         168.126.63.1
    Address:        168.126.63.1#53
    
    Non-authoritative answer:
    _acme-challenge.new.lesstif.com text = "slqQSBrs4rToROM7LyEeBVvI92YXi3JJ-RK6S5OBKNc"
    
    Authoritative answers can be found from:
  6. 기존 let’s encrypt 발급 터미널로 간 후에 엔터를 입력합니다.
  7. 정상 발급되었는지 확인하고 웹 서버를 설정합니다.
    Waiting for verification...
    Cleaning up challenges
    
    IMPORTANT NOTES:
     - Congratulations! Your certificate and chain have been saved at:
       /etc/letsencrypt/live/new.lesstif.com/fullchain.pem
       Your key file has been saved at:
       /etc/letsencrypt/live/new.lesstif.com/privkey.pem

Boot2Docker Volume Disk Resize

Boot2Docker에서 “장치에 남은 공간 없음” 오류가 발생합니까?

많은 수의 이미지와 함께 Boot2Docker를 사용하거나 작업 중인 이미지가 매우 큰 경우 Boot2Docker VM의 볼륨 공간이 부족하면 문제가 발생할 수 있습니다. 솔루션은 먼저 볼륨을 복제한 다음 디스크 파티셔닝 도구를 사용하여 크기를 조정하여 볼륨 크기를 늘리는 것입니다. (GParted)[ http://gparted.sourceforge.net/download.php/index.php ]는 무료 ISO이고 VirtualBox와 잘 작동하기 때문에 사용하겠습니다.

1. Boot2Docker의 VM을 중지합니다.

$ boot2docker stop 

Boot2Docker는 VirtualBox의 기본 도구로 크기를 조정할 수 없는 VMDK 이미지와 함께 제공됩니다. 대신 VDI 볼륨을 만들고 VMDK 볼륨을 여기에 복제합니다.

2. VirtualBox 명령줄 도구를 사용하여 VMDK 이미지를 VDI 이미지로 복제합니다.

$ vboxmanage clonehd /full/path/to/boot2docker-hd.vmdk /full/path/to/<newVDIimage>.vdi —format VDI —variant Standard

3. 필요에 적합한 크기를 선택하여 새 복제 볼륨의 크기를 조정합니다. 많은 컨테이너를 회전하거나 컨테이너가 특히 큰 경우 더 큰 것이 좋습니다.

$ vboxmanage modifyhd /full/path/to/<newVDIimage>.vdi —resize <size in MB>

4. (GParted)[ http://gparted.sourceforge.net/download.php/ ] 와 같은 디스크 파티션 도구 ISO를 다운로드합니다 . Boot2Docker VM의 IDE 버스에 ISO를 추가합니다. ISO를 추가하기 전에 버스를 생성해야 할 수도 있습니다.

5. VirtualBox의 Boot2Docker 이미지에 새 VDI 이미지를 추가합니다.

6. Boot2Docker VM에 대한 설정에서 CD/DVD가 부팅 순서 목록 의 맨 위에 있는지 확인 합니다.

7. VirtualBox에서 Boot2Docker VM을 시작하면 디스크 파티션 ISO가 시작됩니다. 

GParted를 사용하여 GParted Live(기본 설정) 옵션을 선택합니다. 기본 키보드, 언어 및 XWindows 설정을 선택하면 GParted 도구가 시작되고 생성한 새 VDI 볼륨이 표시됩니다. VDI를 마우스 오른쪽 버튼으로 클릭하고 크기 조정/이동 을 선택합니다 . 볼륨을 나타내는 슬라이더를 최대 크기로 끌어 크기 조정/이동 을 클릭 한 다음 적용 을 클릭 합니다. GParted를 종료하고 VM을 종료합니다. VirtualBox의 Boot2Docker VM용 IDE 컨트롤러에서 GParted ISO를 제거합니다.

8. VirtualBox에서 또는 명령줄( boot2docker start)을 사용하여 Boot2Docker VM을 시작하여 볼륨 변경 사항이 적용되었는지 확인합니다.

시놀로지 4TB디스크를 8TB디스크로 교체하기

DS918+와 4TB 하드디스크 한 개를 사용하고 있는데요. 8TB 하드디스크 네 개로 교체하고 싶어요.

  • 4TB 하드디스크의 공간이 가득 찼습니다. 8TB 하드디스크 4개 장착 후 raid5를 만들어서 24TB의 공간을 사용하고 싶습니다.
  • 나스는 24시간 계속 사용합니다. 8TB 하드디스크로 교체하는 동안에도 나스 접속이 끊기지 않아야 합니다.

8TB 하드디스크 4개를 raid5로 만듭니다.

DS920+는 핫스왑 기능을 제공하므로 나스를 계속 사용하면서 하드디스크를 교체할 수 있습니다. 8TB 하드디스크 4개를 사용하여 raid5가 완성되는 데는 5일 정도 소요 되었지만 실제로 작업한 시간(하드디스크 교체하기, 마우스 클릭하기 등)은 10분 정도밖에 되지 않습니다.

  • 현재는 1번 베이에 4TB 하드디스크가 장착되어 있고 나머지 베이는 비어 있습니다. 스토리지 풀은 shr방식입니다. 다음 과정을 거쳐서 8TB 하드디스크 4개로 raid5를 만듭니다.
  • 과정 1
    4TB 디스크 1개와 8TB 디스크 1개를 레이드1으로 만듭니다. 레이드1이 된 이후에는 볼륨의 크기가 4TB가 됩니다.
  • 과정 2
    4TB 디스크를 8TB 디스크로 교체 후 수리를 진행합니다. 수리가 끝나면 8TB 디스크 2개로 raid1이 되고 볼륨의 크기가 8TB가 됩니다.
  • 과정 3
    8TB 디스크 2개로 raid1 상태에서 8TB 디스크 2개를 추가하여 raid5로 변경합니다. raid5가 된 이후에는 볼륨의 크기가 24TB가 됩니다.

과정 1. 4TB와 8TB로 raid1 만들기.

  • 2번 베이에 8TB 디스크를 장착 후 “스토리지 풀 > 작업 > 드라이브 추가”를 클릭합니다. 드라이브 2를 선택합니다.
  • 스토리지 풀 화면에서 1번 베이의 4TB 디스크와 2번 베이의 8TB 디스크가 사용된 것을 볼 수 있습니다.
  • 스토리지 풀 확장하는 작업이 완료되면 스토리지 풀의 총 용량은 4TB, 볼륨의 총 용량도 4TB가 됩니다.
  • 스토리지 풀 확장이 완료되는데 13시간 정도 소요되었습니다.

과정 2. 4TB 교체 후, 8TB와 8TB로 raid1 만들기.

  • HDD/SSD 화면에서 4TB 하드디스크에 해당하는 드라이브(이번 사례에서는 드라이브 1)를 선택 후 “작업 > 비활성화”를 클릭합니다.
  • 드라이브 1 옆에 “비활성화됨”이 표시되면 4TB 하드디스크를 제거하고 새로운 8TB 디스크를 장착합니다. (기존 4TB 드라이브와 미러링 된 드라이브 외 새로운 드라이브 추가)
  • “스토리지 풀 > 작업 > 수리”를 클릭합니다. 드라이브 1을 선택합니다.
  • 2번 베이 하드디스크(Drive 2)의 내용을 1번 베이 하드디스크(Drive 1)로 복제하므로 Drive 2는 읽기작업이 발생하고 Drive 1은 쓰기작업이 발생하는 것을 리소스 모니터에서 확인할 수 있습니다.
  • 수리가 완료되는데 15시간 정도 소요되었습니다
  • 수리가 완료되면 스토리지 풀의 총 용량은 8TB로 늘어나지만, 사용한 용량은 여전히 4TB 그대로입니다. shr방식을 사용하는 경우에는 볼륨의 크기가 저절로 늘어나지 않기 때문입니다.        (DSM 6.2.3 부터는 자동으로 최대 크기로 늘어남)
  • 볼륨의 크기를 8TB로 늘립니다. “볼륨 > 작업 > 구성”을 클릭하고 “최대” 버튼을 클릭합니다. 그러면 “할당된 크기 수정(GB)” 칸의 숫자가 스토리지 풀이 사용할 수 있는 최대 용량으로 입력됩니다. “확인” 버튼을 클릭하면 10초 정도 후에 볼륨의 총 용량이 8TB로 변경됩니다.

과정 3. 8TB 디스크 2개 추가하기.

  • 3번 베이, 4번 베이에 8TB 디스크를 각각 장착한 다음 “스토리지 풀 > 작업 > 드라이브 추가”를 클릭합니다. 드라이브 3, 드라이브 4를 선택하고 다음을 클릭합니다. “설정 확인” 화면에서 총 용량이 21.82TB로 나오는지 확인합니다.
  • 스토리지 풀 확장이 완료되는데 90시간 정도 소요되었습니다.
  • 스토리지 풀 확장하는 작업이 완료되면 스토리지 풀의 총 용량은 24TB로 늘어나지만, 사용한 용량은 여전히 8TB 그대로입니다.  사용하지 않은 용량 16TB를 볼륨에 추가해야 합니다.
  • “볼륨 > 작업 > 구성”을 클릭하고 “최대” 버튼을 클릭합니다.
  • 최종적으로 볼륨의 크기가 24TB가 되었습니다.

8TB 디스크의 파티션 모습.

지금까지의 과정은 이벤트 로그와 알림에 기록되어 있습니다. 기록을 보면 “과정 3. 8TB 디스크 2개 추가하기”에서 동기화 작업이 네 번 나오는데요. 4TB 하드디스크로 스토리지 풀을 최초로 만들때 shr방식으로 설정했기 때문입니다. shr방식에서 더 큰 용량의 하드디스크로 교체하면 하드디스크의 파티션이 최초의 스토리지 풀 크기(4TB)와 나머지 크기(8TB에서 최초의 스토리지 풀 크기를 제외한 나머지)로  나누어집니다.  그래서 8TB디스크 4개 모두 두 개의 파티션으로 나누어져 있습니다. 또한 raid1에서 raid5로 변경하는 경우에 디스크 두 개를 한 번에 추가해도 변경작업(동기화 작업)은 한 개씩 이루어집니다. 그래서 다음과 같이 총 네 번의 동기화 작업이 진행됩니다.

  • 첫 번째 : 디스크 3개의 4TB  파티션을 동기화.
  • 두 번째 : 디스크 3개의 4TB  파티션을 제외한 부분 동기화.
  • 세 번째 : 디스크 4개의 4TB  파티션을 동기화.
  • 네 번째 : 디스크 4개의 4TB  파티션을 제외한 부분 동기화.

네 번의 동기화가 모두 끝나면 두 개의 raid5 장치가 생성됩니다. 하나는 4TB 크기 네 개로 raid5이므로 사용가능한 용량은 12TB가 되고, 다른 하나는 8TB에서 4TB를 제외한 크기(결국 4TB 크기) 네 개로 raid5이므로 마찬가지로 12TB가 됩니다. 그리고 두 개의 12TB 공간을 LVM을 사용하여 묶어서 총 24TB 크기의 스토리지 풀이 됩니다.

  • 지금까지의 과정을 “모든 알림”에서 볼 수 있습니다.
  • fdisk 명령어를 사용해서 파티션이 어떻게 나눠져 있는지 확인할 수 있습니다.
  • sda5, sdb5, sdc5, sdd5가 md2에 사용되고 sda6, sdb6, sdc6, sdd6이 md3에 사용되었습니다.

Elastic Search Index and Shade Split point

여러개의 샤드 vs 인덱스 쪼개기

다나와 서비스의 상품갯수는 급격하게 늘어나고 있습니다. 몇달전 4~5억건이었던 상품이 7억건에 육박하고 있는데요. 현재 사용하고 있는 패스트캣 검색엔진에서는 대량의 문서들을 여러개의 인덱스로 나누어 색인하고 있습니다.

검색할때는 나눈 인덱스들을 하나로 합쳐서 검색하고 있는데요. 엘라스틱서치에도 여러 인덱스를 하나로 합쳐서 한번에 검색하는 기능이 있어서 지금처럼 인덱스를 쪼개서 사용하는 것도 가능한 시나리오입니다. 참고로 얘기하면, 이렇게 데이터를 범위나 카테고리로 나누어 관리하는 기법을 파티셔닝이라고 합니다.

먼저 인덱스를 하나로 가져가든 여러개로 나누든, 샤드 하나의 크기는 비슷하게 설정해야 할텐데요, 적절한 샤드의 크기를 먼저 정해야 할 것 같습니다. 몇차례 구글링을 한결과 엘라스틱서치의 공식블로그에서 도움이 될만한 글를 찾을수 있었습니다.

TIP: 작은 샤드는 작은 세그먼트를 만들며 부하를 증가시킵니다. 평균 샤드 크기를 최소한 수 GB와 수십 GB 사이를 유지하세요. 시간 기반 데이터를 사용한 과거 사례를 보면, 20GB ~ 40GB 정도의 사이즈가 적당합니다.

샤드크기는 수GB에서 수십GB 사이가 적당하며, 경험상 시계열 데이터의 경우 20GB~40GB가 적당하다고 합니다. 그리고 아래에서 또다른 팁을 발견할수 있었습니다.

TIP: 하나의 노드에 저장할 수 있는 샤드의 개수는 가용한 힙의 크기와 비례하지만, Elasticsearch에서 그 크기를 제한하고 있지는 않습니다. 경험상 하나의 노드에 설정한 힙 1GB 당 20개 정도가 적당합니다. 따라서 30GB 힙을 가진 노드는 최대 600개 정도의 샤드를 가지는 것이 가능하지만, 이 보다는 적게 유지하는 것이 더 좋습니다.

힙메모리 30GB로 엘라스틱서치를 구동시 샤드는 최대 600개 정도라고 합니다. 이미 32GB 를 힙에 할당할 생각을 하고 있으므로, 활성화된 인덱스가 50개라고 한다면, 인덱스당 600샤드 / 50 인덱스 = 12 로 인덱스당 최대 12개의 샤드를 설정할수 있을 겁니다. 일단 샤드갯수의 최대치는 넉넉한것 같으므로, 많아서 문제가 될것같지는 않습니다.

하나의 샤드를 20GB~40GB로 설정한다면, 7억건의 상품은 몇개의 샤드로 나눠지게 될까요? 다나와 상품기준으로는 15개의 샤드로 나눠지게 됩니다. 물론 엘라스틱 서치 블로그에서는 시계열 데이터에 대한 팁이라서 상품과는 문서의 특성이 다릅니다. 대부분은 웹서버나 DB 로그데이터 일텐데요, 로그스태시의 파싱모듈을 확인해보면 한 로그내의 필드수가 10개 내외로 매우 적습니다. 반면에 상품의 필드는 수십개는 기본입니다.

이러한 문서특성의 차이로 검색과 색인시 한개 문서에 들어가는 리소스와 시간이 더 투여됩니다. 그러므로, 상품문서는 하나의 샤드를 20GB 보다는 조금 더 작게 나누면 여러 서버에 더 잘게 분산이 되어 전체적인 응답시간은 더 빨라질겁니다. 우리는 샤드당 약 5GB로 설정하고 테스트 했는데, 빠른 응답속도를 얻을 수 있었습니다.

그럼, 인덱스를 나누는것과 샤드를 나누는것 어떤것이 적합할까요? 어치피 샤드는 여러 서버에 분산되어 병렬 및 병행 (참고: https://soy.me/2015/01/03/concurrent/)으로 검색이 되므로, 인덱스가 같던 다르던 상관은 없습니다. 검색의 기본 단위는 샤드이기 때문이죠. 따라서 인덱스를 나누는 것은 운영의 편의성을 고려할때 선택하는 방법입니다. 장애없는 운영의 측면에서 생각해보면, 큰 덩어리 하나를 다루는 것은 부담스러워도, 작은 덩어리 여러개를 다루는 것이 번거롭긴해도 그만큼 장애 가능성을 낮추는 방법이 됩니다.

전체색인을 빠르게 하려면

전체색인을 할 경우 인덱스 하나가 7억건이라면 색인이 모두 끝날때까지 약 3-4시간이 소요될것이고, 검색에 노출되기 까지 이시간을 고스란히 기다려야 합니다. 더 문제가 되는것은 전체색인 도중에도 상품의 가격은 계속해서 변하게 되는데 이 변경분을 전체색인후에 일괄적용을 해야하며, 대기시간이 길수록 일괄적용시간도 늘어나게 됩니다. 그러므로, 최대한 전체색인을 빠르게 해야하는데, 이를 위해서는 문서를 입력하는 REST 클라이언트를 멀티스레드로 여러개 생성하여 동시입력량을 늘려야 합니다. 이때 Bulk Insert 를 쓰는것은 기본이구요.

하지만, 엘라스틱서치의 Write IO도 고려해야 합니다. 동시입력량을 늘리면, 서버의 CPU와 Disk IO중 둘중 하나는 최대치에 이를것이고, 더이상 색인속도는 늘어나지 않게 됩니다. 우리가 경험한 최대 색인속도는 500KB 상품문서 기준으로 16000건/초 였습니다. 이때 CPU는 32코어로 90%를 사용했으니 활용도는 매우 높다고 할수 있습니다. (참고: https://danawalab.github.io/elastic/2020/07/06/Elasticsearch-Index.html)

결국은 더 빠른 색인을 위해서는 하나의 인덱스를 여러개로 나눠야 합니다. 통으로 4시간이 걸리는 문서를 10개의 인덱스로 나누면 색인시간이 서버를 공유하므로 정확히 1/10이 될수는 없지만, 그대로 각각 40분정도로 병행완료가 됩니다.

상품DB의 특성상 우리는 카테고리군별로 인덱스를 나누고 있습니다. 카테고리별로 인덱스를 나눌때의 장점은 특정카테고리만 검색할때 해당 인덱스만 검색하면 되므로, 검색부하가 현저히 감소하게 됩니다. 우리는 인덱스도 나누고 샤드도 2-3개로 나누어 전체적인 검색응답시간을 최대한 단축하는 방향으로 설계했습니다.

레플리카 갯수는 몇개로?

고가용성을 추구할때 빼놓을 수 없는 것이 레플리카인데요, 레플리카는 레플리카 샤드를 줄여서 얘기하는 것으로, 프라이머리 샤드에 종속됩니다. 우리말로는 복제본 이라고도 하죠. 복제본은 분산 데이터 시스템에서는 동일한 역할을 담당하는데요, 하드웨어 장애를 극복하고 검색과 같은 읽기처리량을 향상시키는 것입니다.

그런데 읽기성능이 좋아진다는 것은 쓰기성능이 낮아진다는 얘기도 됩니다. 왜냐하면, 복제본을 여러개 만들기 위해서는 그만큼 문서색인시에 쓰기작업도 복제본 갯수만큼 발생하기 때문이죠. 하나의 서버만 본다면 1이지만, 전체클러스터 입장에서는 복제본이 열개면 10의 쓰기가 일어나는 것입니다. 문서가 색인될때 구지 모든 서버의 IO발생하게 만들 필요는 없을겁니다.

또한 복제본의 갯수는 동시에 장애가 발생할 노드를 몇개 까지 허용하는지에 달려있습니다. 복제본이 1개라면 하나의 노드가 죽어도 검색서비스는 유지됩니다. 하지만, 이제 복제본은 0개가 되므로, SA가 빨리 노드를 복구하지 않으면, 다른 또하나의 노드가 죽을때 검색서비스에는 장애가 생깁니다.

만약 회사내에 장애 복구시스템이 잘 갖춰져 있다고 하면, 복제본은 1개로도 가능합니다. 복제본이 2라면 서버가 연속 2개 죽어도 상관이 없으므로, 마음을 느긋하게 가질수 있습니다. 하지만 전체 클러스터에서 서버가 2개 빠지고도 부하를 충분히 견딜수 있게 서버를 배치해 놓아야 합니다. 우리는 카테고리별 인덱스의 읽기성능을 고려해서 부하가 높은 인덱스는 복제본 2를 나머지는 1을 설정할 계획입니다.

결론

nginx로그와 같은 로그성 문서는 색인을 하고 나면 수정이 필요없는 정적인 컨텐츠인 반면에, 상품문서는 색인이 끝나도 계속 갱신이 되어야 하는 살아있는 컨텐츠입니다. 그렇기 때문에, 동적색인이 원활하고 장애도 대비할수 있으며, 검색성능도 높은 설계가 필요합니다. 그리고 엘라스틱서치를 사용하여 검색시스템을 설계할때 운영자가 할수 있는 최선의 방법은 문서와 샤드를 잘 관리하는 것입니다. 따라서 견고한 검색시스템을 위해 인덱스와 샤드를 어떻게 설정해야 하는지에 대해 살펴봤습니다.

참고

https://www.elastic.co/kr/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster

https://medium.com/kariyertech/elasticsearch-cluster-sizing-and-performance-tuning-42c7dd54de3

https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html

Kubernetes Virtual Storage (Ceph) Installation

설치에 필요한 도구로 Rook을 사용할 예정입니다. Rook은 오픈소스 클라우드 네이티브 스토리지 오케스트레이터로, 클라우드 네이티브 환경과 기본적으로 통합할 수 있는 다양한 스토리지 솔루션 세트에 대한 플랫폼, 프레임 워크 및 지원합니다. Rook을 통해 Ceph 가상스토리지를 구성하고 공유 파일 시스템을 적용하도록 하겠습니다.

Rook 구성도

Rook은 쿠버네티스 POD에서 실행되며, Ceph, EdgeFS등 가상솔루션을 POD로 배포하여 관리하는 도구입니다. agent를 통해 Ceph, EdgeFS등 가상솔루션을 관리하고, OSD를 통해 데이터를 영구저장합니다.

/images/2020-01-28-kubernetes-rook-ceph/Untitled.png

Ceph vs EdgeFS

Rook에서 제공하는 가상스토리지는 EgdeFS와 Ceph 외에도 다양하게 지원하지만 안정적인 버전은 아래 두가지만 지원합니다.

  • EdgeFS: 데이터베이스처럼 대용량 스토리지가 필요할때 사용됩니다.
  • Ceph: 공유 확장에 특화되어 있는 스토리지가 필요할때 사용됩니다.

공유나 확장에 특화되어 있는 Ceph를 설치하도록 하겠습니다.

Ceph 스토리지 유형

Ceph는 Block, Object, File 기반으로 데이터를 사용할 수 있습니다. 각 유형에 따라서 사용하는 기능에 차이가 있습니다.

  • Block Stroage: 단일 POD에 storage 제공합니다.
  • Object Storage: 애플리케이션이 쿠버네티스 클러스터 내부 또는 외부에서 액세스 할수있느 데이터를 IO 할수있고, S3 API를 스토리지 클러스터에 노출을 제공합니다.
  • Shared Stroage: 여러 POD에서 공유할 수있는 파일 시스템기반 스토리지입니다.

Shared Storage 구성도

이번에 설치해볼 Shared Storage 구성입니다. Ceph 클러스터에 데이터를 저장하고 Ceph를 통해 POD들과 데이터가 공유가 됩니다.

/images/2020-01-28-kubernetes-rook-ceph/Untitled%201.png

Ceph 설치

테스트 환경

쿠버네티스가 설치된 환경이 필요합니다. 설치방법은 쿠버네티스 고가용성 클러스터 구성 블로그를 통해 설치진행 바랍니다.

OS: ubuntu:18.04
Kubernetes: 1.16.4

Ceph 소스 다운로드 및 POD 배포

Rook은 별도의 설치가 없고 github으로 Ceph, EdgeFS 가상스토리지 솔루션을 쿠버네티스에 배포할 수 있도록 제공하고 있습니다.

$ git clone --single-branch --branch release-1.2 https://github.com/rook/rook.git

아래 경로에 보면 common.yaml, operator.yaml이 있습니다. kubectl 명령어를 통해 배포 합니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/common.yaml
$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/operator.ymal
$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/cluster.yaml

cluster.yaml을 배포하게 되면 POD 중 OSD가 Running 상태인지 확인이 필요합니다. 변경되는 시간이 약 1 ~ 3 분 정도 소요됩니다.
테스트 환경에 따라 OSD 갯수가 차이가 있을 수 있습니다.

$ kubectl get pod -n rook-ceph

/images/2020-01-28-kubernetes-rook-ceph/Untitled%202.png

OSD Running 상태까지가 ceph 클러스터 구성이 완료되었고, Shared Storage 유형을 적용해보겠습니다.

Shared Storage 유형 적용

아래 명령어를 실행하게 되면 MDS POD가 배포가 됩니다. 약 1 ~ 3분 정도 소요됩니다. Shared Storage 옵션을 변경할 수 있는데 자세한 내용은 ceph-filesystem-crd 통해 확인바랍니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/filesystem.yaml

StorageClass Driver 적용

StorageClass는 POD에서 Ceph 데이터 풀에 접근하기 위해 사용되는 드라이버입니다. kubectl 명령어를 통해 적용합니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/csi/cephfs/storageclass.yaml

Shared Storage 확인

정상적으로 적용이 되었는지 확인하는 방법압니다. 아래 결과 처럼 myfs가 생성되어 있습니다.

$ kubectl get CephFileSystem -A

결과)

/images/2020-01-28-kubernetes-rook-ceph/Untitled%203.png

Shared Storage 테스트

kube-registry를 배포하면 PVC, docker-registry POD가 배포됩니다. 컨테이너 내부에 접근하여 /var/lib/registry 디렉터리에 dummy 파일을 생성 하여 다른 POD에서 공유되어 보여지는지 확인합니다.

$ kubectl apply -f rook/cluster/examples/kubernetes/ceph/csi/cephfs/kube-registry.yaml

정리

Rook이라는 도구를 이용해서 Ceph를 설치해보았습니다. Ceph를 관리하려면 러닝커브가 있지만 Rook이라는 도구를 이용해서 Ceph 관리와 쿠버네티스와 연동을 쉽게 할 수 있습니다.