Skip to main content

K3s on Raspberry Pi Cluster

· 13 min read

이번에는 경량 Kubernetes라고 이야기하는 K3s를 Raspberry Pi 클러스터상에 구동하려고 한다. 순수하게 개인의견으로 작성하였고 절대 제품이나 부품홍보를 하고자 하는 의도는 전혀 없다.

K3s?

K3s는 Rancher Lab에서 최소자원을 사용하는 Kubernetes 클러스터 구성을 위한 솔루션으로 시작되었고 2019년 3월 12일 현재 0.2버전이 릴리즈된 상태이다. 바이너리 전체가 40mb가 되지 않고 설치가 쉽다는 점에서 최근 트위터 상에서 이슈가 되고 있는 프로젝트라고 할 수 있다.

주로 Edge, IoT 등 저전력, 저사양 기반 ARM계열 컴퓨팅에 최적화 되어 있고 실제 실험적이긴 하지만 간단한 기능이나 baremetal 기반 클러스터 테스트를 집에서 해보기에는 딱 좋은 프로젝트라 할 수 있다. 이미 vSphere, OpenStack기반으로 테스트는 차고 넘치게 해봤지만 일단 물리적인 케이스부터 보고나면 하드웨어를 좋아하는 사람들에게는 아주 재미있는 장난감이 아닐수 없을 것이다.

K3s Github 상세 설명에 보면 Cloud Provider, Storage Plugin은 제거하였고 default 저장소가 etcd가 아닌 sqlite3으로 되어있다고 한다.

사전 준비사항

  • 최소 2개 이상의 Raspberry Pi 2B/3B/3B+, 4ea
    오픈마켓에서 할인쿠폰 적용해서 Raspberry Pi 3B+, 4ea를 166,820원(대당 42,000원) 정도에 구매하였다.
    최저가 검색으로 대당 46,000원 정도 했던것 같다.

  • Stackable Case
    iUniker Raspberry Pi Cluster Case 강추!! (개인적으로 쿨러와 디자인이 맘에 듬)
    배송비포함 29.19달러, 약 33,000원

  • micro SDHC 4ea
    16GB로도 충분하지만 삼성전자 micro SDHC CLASS10 UHS-I EVO (32GB), 4ea를 오픈마켓에서 사게되면 배송료 포함해서 8,500원 * 4ea = 34,000원에 구매가 가능하다. 오픈마켓에서는 개당 배송료를 내야한다. 하지만 쿠팡에서는 2ea를 로켓배송으로 15,380원에 구매가 가능하므로 약 31,000원에 4개를 구매할수 있다.

  • 멀티충전기
    1만원대 후반에서 2만원 초반이면 6포트 충전기를 구매할수 있는데 구매했던 가장 큰 기준은 Pi 4대를 동시에 2.5A 전류를 안정적으로 공급하려면 최대 10A를 지원하는 멀티 충전기를 사야했었고 4-5포트 짜리 충전기들은 대부분 최대 전류가 8A로 충족하지 못해 4포트만 사용하더라도 안정적인 전류 공급을 위해 6포트 충전기로 선택하였다.
    쿠팡 로켓배송 - 포*지 가정용 6포트 급속 멀티 충전기, 22,900원

  • micro 5pin 20cm 2.4A 지원 케이블 4ea
    Pi 권장 전류가 2.5A라고 했지만 2.4A, 3A 짜리중에 저렴한 2.4A 지원 숏케이블로 구매하였다.
    오픈마켓에서 배송료 포함, 7800원

  • UTP Cat5e 30cm 케이블 4ea
    그냥 제일싼걸로 오픈마켓에서 배송료 포함 4,100원에 구매하였다.

  • 기가비트 지원되는 5포트 이상 스위치 허브(공유기)
    집에 있던 공유기 활용 (iptime A1004) 하였지만 최저 5포트 이상 스위치 허브중 제일 싼 모델은 16,000원대로 가격 형성중이다.

실제 위 스펙으로 대충 구매를 진행하게 되면 18.4 + 3.3 + 3.1 + 2.3 + 0.8 + 0.4 + 1.6 = 29.9만원 정도 소요가 될 것으로 예상된다. 집에 굴러다는 부품이나 충전기, 케이블, SD카드들을 활용하면 25만원 이내로도 충분히 가능하다.

구매 제품 조립

조립은 그다지 어렵지 않은데 케이스 구매시 제공되는 방열판(CPU, GPU, RAM)을 꼼꼼하게 붙이고 쿨러를 GPIO에 연결한다.
그렇게 어려운 점은 없지만 본체를 케이스에 고정할때 너트가 작아 손이 큰 사람은 조금 힘들 수도 있을 것 같다.

케이스의 CPU 쿨러가 화룡점정이다.

cases
heat
cooler 3stack charger full complete

OS 설치

SD카드에 설치는 MacOS상에서 진행하였다.

Raspbian Lite를 내려받아 Etcher를 사용하여 OS를 설치한다.

자세한 추가적인 설치방법은 다음 링크를 통해서도 확인이 가능하다.
Installing operating system images

환경 설정

Mac에서는 /Volumes/boot에 마운트가 된다. OS마다 다르지만 Linux에서는 /mnt/boot, Windows에서는 boot 로 마운트가 된다.

SSH Service 자동 활성화를 위해 위 OS별 mount된 root 경로에 ssh 빈 파일을 생성하게 되면 reboot이후에 SSH 접속이 가능해진다.

$ sudo touch /Volumes/boot/ssh

또한 container 사용을 위해 root경로의 cmdline.txt 파일 마지막에 cgroup 설정을 추가한다.

cgroup_memory=1 cgroup_enable=memory

SD카드를 만들고 각각의 Pi에 장착후에 UTP케이블과 전원을 모두 연결한다. 부팅이 완료되면 default id/pass 인 pi/raspberry로 로그인 하고 sudo raspi-config 를 통해 패스워드 변경, hostname 설정, GPU memory split 설정 등을 완료하자.
나중에는 PXE booting 및 ansible 자동화로 구현하면 무인환경 설치가 가능할것 같다. (Edge Computing)

┌───────────────────┤ Raspberry Pi Software Configuration Tool (raspi-config) ├────────────────────┐
│ │
│ 1 Change User Password Change password for the current user │
│ 2 Network Options Configure network settings │
│ 3 Boot Options Configure options for start-up │
│ 4 Localisation Options Set up language and regional settings to match your location │
│ 5 Interfacing Options Configure connections to peripherals │
│ 6 Overclock Configure overclocking for your Pi │
│ 7 Advanced Options Configure advanced settings │
│ 8 Update Update this tool to the latest version │
│ 9 About raspi-config Information about this configuration tool │
│ │
│ │
│ │
│ <Select> <Finish> │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
  • 1 Change User Password
  • 2 Network Options - hostname
    • k3s-master, k3s-slave-01, k3s-slave-02, k3s-slave-03
  • 4 Localisation Options - TimeZone
    • Asia, Seoul
  • 7 Advanced Options - GPU Memory split
    • 16mb

모두 완료가 되었으면 pi들을 재기동하자.

$ sudo reboot

k3s 클러스터 생성

Server 기동

armhf(arm hard float) 지원이 되는 최신 릴리즈 v0.2.0를 다운받는다.

$ wget -O k3s https://github.com/rancher/k3s/releases/download/v0.2.0/k3s-armhf && \
chmod +x k3s && \
sudo mv k3s /usr/local/bin/k3s

Master node 기동 (백그라운드)

$ sudo k3s server &

해당 node를 Control plane 형태로 분리시켜 workload에서 제외하려면 --disable-agent 옵션을 사용한다.

& k3s server --disable-agent

정상적으로 k3s 기동이 완료되면 /etc/rancher/k3s/k3s.yaml에서 Kubeconfig를 확인할수 있다. 그리고 node 상태도 확인이 가능하다.

$ sudo k3s kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-master Ready <none> 21h v1.13.4-k3s.1

node 추가

/var/lib/rancher/k3s/server/manifests 에서 TOKEN을 확인한다.

$ sudo cat /var/lib/rancher/k3s/server/node-token
K100fa5235031f2b8e92e01b8bd3255142422a7aeaa47657ad4c68969d35cddbf3a::node:431342ac6204466e8f81445edb8c2e3a

worker node에 접속한다음 동일하게 최신 릴리즈 v0.2.0를 다운받는다.

$ wget -O k3s https://github.com/rancher/k3s/releases/download/v0.2.0/k3s-armhf && \
chmod +x k3s && \
sudo mv k3s /usr/local/bin/k3s

위에서 나온 TOKEN값과 Kube API Endpoint정보로 node들을 차례로 추가 시키면 모든 작업이 완료된다.

$ export NODE_TOKEN="K100fa5235031f2b8e92e01b8bd3255142422a7aeaa47657ad4c68969d35cddbf3a::node:431342ac6204466e8f81445edb8c2e3a"
$ export MASTER_IP="https://192.168.0.14:6443"
$ sudo k3s agent --server https://${MASTER_IP}:6443 --token ${NODE_TOKEN} &

완성된 클러스터를 확인한다. 외부 로컬에서 확인하려면 /etc/rancher/k3s/k3s.yaml 파일을 ~/.kube/config에 추가하면 된다. 클러스터 내부에서 kubectl 명령은 k3s 바이너리 내부에 포함되어 있으므로 sudo k3s kubectl 명령을 사용하였다.

$ sudo k3s kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k3s-master Ready <none> 22h v1.13.4-k3s.1 192.168.1.14 <none> Raspbian GNU/Linux 9 (stretch) 4.14.79-v7+ containerd://1.2.4+unknown
k3s-slave01 Ready <none> 21h v1.13.4-k3s.1 192.168.1.15 <none> Raspbian GNU/Linux 9 (stretch) 4.14.79-v7+ containerd://1.2.4+unknown
k3s-slave02 Ready <none> 10h v1.13.4-k3s.1 192.168.1.16 <none> Raspbian GNU/Linux 9 (stretch) 4.14.79-v7+ containerd://1.2.4+unknown
k3s-slave03 Ready <none> 10h v1.13.4-k3s.1 192.168.1.17 <none> Raspbian GNU/Linux 9 (stretch) 4.14.79-v7+ containerd://1.2.4+unknown

node 상세정보를 보면 기본적으로 K8s v1.13.4, runtime은 containerd를 사용하고 있음을 알 수 있다.

$ sudo k3s kubectl get svc --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 21h
kube-system kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP,9153/TCP 21h
kube-system traefik LoadBalancer 10.43.19.160 192.168.1.14,192.168.1.15 80:32304/TCP,443:31690/TCP 21h

Rancher쪽에서도 오늘날짜(3/12)로 F5가 Nginx를 인수하는것을 예견했던 것일까?
Service를 확인하면 traefik이 기본으로 되어있다. 아래처럼 기본적으로 loadbalancer로 활용되고 있는 traefik을 Helm Chart CRD를 통해 배포된것을 확인할 수 있다. 또한 얼마전 졸업한 CoreDNS도 보인다.

$ sudo k3s kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-7748f7f6df-qflx9 1/1 Running 0 21h
kube-system helm-install-traefik-dqqg9 0/1 Completed 0 21h
kube-system svclb-traefik-598fd65c97-4xtkf 2/2 Running 0 21h
kube-system svclb-traefik-598fd65c97-vbsqv 2/2 Running 0 19h
kube-system traefik-6876857645-2sqg9 1/1 Running 0 21h

$ sudo k3s kubectl get crd
NAME CREATED AT
addons.k3s.cattle.io 2019-03-11T16:46:22Z
helmcharts.k3s.cattle.io 2019-03-11T16:46:22Z
listenerconfigs.k3s.cattle.io 2019-03-11T16:46:22Z

정리

아주 적은비용(?)으로 취미삼아 k3s 클러스터를 구성해봤다.
아직 ARM계열에서 kubernetes workload를 구동하는 것은 시기상조이긴 하지만 기존에 kubeadm을 가지고 pi에 배포하는것에 비하면 설치 난이도나 자원사용량 측면에서 장점이 많은 프로젝트이다.
해외 블로그나 트위터를 보면 최근 k3s에 대한 관심도가 높아지는것을 확인할 수 있는데 단순히 취미생활만이 아니라 IoT, Edge에서의 Serverless Workload 수행이라던지 ARM 계열 최적화된 모습만으로도 충분히 가능성은 보여준것 같다.
Rancher 2.0 이후로 Kubernetes 연관된 관심도가 떨어졌었는데 엔지니어들의 관심을 끄는데는 성공한듯 하고 AWS의 Greengrass, Firecracker와 동일선상에서 봐도 견줄만한 가치가 있다고 생각된다.