Kubernetes

Kubernetes에서 Go application을 Unikernel로 실행하기

chaenii 2021. 12. 30. 17:39

Pre-requisites

kubernetes Cluster의 master에 반드시 worker node가 1개 이상 있어야하며, 하나 이상의 node는 hardware virutalizationenable 상태여야합니다. hardware virtualization이 안되는 경우에는 아래를 참고하세요.

 

✅  hardware virtualization이 안되는 경우

KubeVirt 설치전에 아래의 명령어를 실행한다.

kubectl create namespace kubevirt

kubectl create configmap -n kubevirt kubevirt-config --from-literal debug.useEmulation=true --from-literal feature-gates="LiveMigration"​

1.  Installing K8s /  Initial Setup

Install Kubectl

curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x ./kubectl
mv kubectl /usr/local/bin/.
sudo mv kubectl /usr/local/bin/.
kubectl version --client

 

Install MiniKube

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube
minikube start --vm-driver=kvm2
mv ./minikube /bin

 

Install KVM tooling

Hypervisor로 사용할 KVM을 설치합니다. 

KVM 설치를 시작하기 전에 CPU가 Hardware virtualization을 지원하는지 확인해야합니다.

아래의 명령어를 실행해서 0이 나온다면, 프로세서가 KVM을 실행할 수 없다는 뜻이고, 나머지 값은 설치를 계속해서 진행할 수 있음을 뜻합니다.

egrep -c '(vmx|svm)' /proc/cpuinfo
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst virt-manager

 

Install KubeVirt

Kubevirt는 Kubernetes에서 Virtual Machines을 관리할 수 있도록 돕는 add-on이다.

Kubevirt하에 생성된 VM은 Scheduling, Networking, Monitoring과 같은 Kubernetes의 기존적인 요소를 따를 수 있다.

✅ kubernetes의 버전에 따라서 호환되는 kubevirt가 달라서 버전을 잘 확인하고 리소스를 배포해야합니다. 게시글 작성 시점에 kubernetes와 docker 버전은 아래에 적어놓았으니 참고바랍니다.

 

export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- - | sort -V | tail -1 | awk -F':' '{print $2}' | sed 's/,//' | xargs)
 
echo $KUBEVIRT_VERSION

kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml

 

- Create a Resource

Kubevirt를 설치한 후, 리소스를 생성한다.

kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml

 

Install Virtctl

Kubevirt는 VM의 직렬 및 그래픽 포트의 빠른 처리와 시작/중지 작업을 처리하기 위해서 virtctl이라는 추가적인 바이너리를 제공하고 있다.

export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- - | sort -V | tail -1 | awk -F':' '{print $2}' | sed 's/,//' | xargs)

curl -L -o virtctl "https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/virtctl-${KUBEVIRT_VERSION}-linux-amd64"

chmod +x virtctl
mv ./virtctl /bin

 

Import CDI(Containerized Data Importer)

CDI(Containerized Data Importer)는 Kubernetes를 위한 영구 스토리지 관리 add-on이다. KubeVirt VM용 PVC에 Virtual Machine Disks를 구축하는 선언적 방법을 제공한다.

✅ kubernetes의 버전에 따라서 호환되는 CDI가 달라서 버전을 잘 확인하고 리소스를 배포해야합니다. 게시글 작성 시점에 kubernetes와 docker 버전은 아래에 적어놓았으니 참고바랍니다.

wget https://raw.githubusercontent.com/lcw729/Unikernel/main/kubevirt/storage-setup.yml
kubectl create -f storage-setup.yml

export VERSION=$(curl -s https://github.com/kubevirt/containerized-data-importer/releases/latest | grep -o "v[0-9]\.[0-9]*\.[0-9]*")
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml

2. 간단한 Go webserver 만들기

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Welcome to my website!")
	})

	fs := http.FileServer(http.Dir("static/"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	http.ListenAndServe(":8083", nil)
}

go program을 Nanos Unikernel로 build하고 deploy한다.

 

- build

GOOS=linux go run goweb.go

 

- Package and deploy

ops run -n -p 8083 goweb
  • ops 설치하기
#install QEMU
sudo apt-get install qemu-kvm qemu-utils


#install Make
sudo apt-get install build-essential
make --version

#install Git
sudo apt-get update
sudo apt-get install git
git version

#install OPS
git clone http://github.com/nanovms/ops $GOPATH/src/github.com/nanovms/ops
cd $GOPATH/src/github.com/nanovms/ops
make deps
make build
cd $GOPATH/src/github.com/nanovms/ops
mv ops /bin

 

- xz image

K8S에서 사용할 형식으로 변환하기 위해서 xz 로 image를 압축한다.

cp .ops/images/goweb.img .
xz goweb.img

3. Google Cloud Bucket에 image 저장하기

pvc stoarge에 import할 이미지를 Google Cloud Bucket에 업로드한다.

 

- Install gsutil CLI 

https://cloud.google.com/storage/docs/gsutil_install

 

gsutil 설치  |  Cloud Storage  |  Google Cloud

의견 보내기 gsutil 설치 이 페이지에서는 HTTPS를 사용하여 명령줄에서 Cloud Storage에 액세스할 수 있는 도구인 gsutil의 설치 및 설정을 설명합니다. gsutil을 설치하면 공개 데이터에 대한 즉시 읽기

cloud.google.com

- Copy my image file to my bucket

gsutil cp gs://<bucket_name>/goweb.img.xz .

- Setting bucket 

현재 업로드한 image에 접근하기 위해서는 비공개로 되어있는 bucket의 설정을 공개로 바꿔주어야한다.

gsutil iam ch allUsers:objectViewer gs://<bucket_name>
gsutil acl ch -u AllUsers:R gs://<bucket_name>/goweb.img.xz .

4. PV, PVC 생성하기

- pvc 생성하기

아래의 링크에서 pvc의 template을 가져와 3에서 생성한 이미지 생성 링크를 넣어줍니다.

https://github.com/lcw729/Unikernel/blob/main/deploy/pvc_fedora.yml

 

GitHub - lcw729/Unikernel

Contribute to lcw729/Unikernel development by creating an account on GitHub.

github.com

  cdi.kubevirt.io/storage.import.endpoint: "https://storage.googleapis.com/<bucket_name>/goweb.img.xz"
kubectl create -f pvc_fedora.yml

 

- pv 생성하기

아직은 pv가 있지 않기 때문에 pvc가 bound 상태가 되지 않을 것입니다.

pv 역시 아래의 링크에서 template을 가져와 생성해줍니다.

https://github.com/lcw729/Unikernel/blob/main/deploy/pv_fedora.yml

 

GitHub - lcw729/Unikernel

Contribute to lcw729/Unikernel development by creating an account on GitHub.

github.com

kubectl create -f pv_fedora.yml

5. 실제 VM 만들기

이제 실제 VM을 만들 수 있다.

wget https://raw.githubusercontent.com/kubevirt/kubevirt.github.io/master/labs/manifests/vm1_pvc.yml
kubectl create -f vm1_pvc.yml
kubectl get vmi

해당 vm이 실행중인 것을 확인하면 유니커널 배포 완료!!!!

 

✅ cdi-deployment나 virt-controller가 계속 restart되는 경우 kubernetes와 Docker version 때문일 수 있으니 버전 업그레이드 해야한다.


✅ 게시글 작성 시점  환경

$ lsb_release -a
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.7 LTS
Release:        16.04
Codename:       xenial

$ Kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:41:01Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:34:54Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}

$ Docker version
Client:
 Version:      17.03.2-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   f5ec1e2
 Built:        Tue Jun 27 03:35:14 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.03.2-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   f5ec1e2
 Built:        Tue Jun 27 03:35:14 2017
 OS/Arch:      linux/amd64
 Experimental: false

https://hackernoon.com/running-linux-applications-as-unikernels-with-k8s-gl2p3yfr

 

Running Linux Applications as Unikernels with K8S | Hacker Noon

If you've read some of my prior articles you might've thought I'd never write this one huh? :) Well here goes.

hackernoon.com

https://docs.ops.city/ops/k8s

 

Kubernetes - Ops

You need access to hardware virtualization. That means a real computer or nested virtualization but nested virtualization is not recommended. It's unclear if these instructions would work on AWS "metal" instances yet as that has not been tried.

docs.ops.city

 

반응형