Kubernetes에서 Go application을 Unikernel로 실행하기
Pre-requisites
kubernetes Cluster의 master에 반드시 worker node가 1개 이상 있어야하며, 하나 이상의 node는 hardware virutalization가 enable 상태여야합니다. 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
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