{"id":40588038,"url":"https://github.com/simplyblock/autoscaling","last_synced_at":"2026-04-02T21:25:42.437Z","repository":{"id":333783414,"uuid":"1098141431","full_name":"simplyblock/autoscaling","owner":"simplyblock","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-01T08:03:43.000Z","size":5174,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-01T09:48:04.447Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simplyblock.png","metadata":{"files":{"readme":"README-NeonVM.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-17T10:02:50.000Z","updated_at":"2026-04-01T08:03:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"63d2f328-de93-4002-afd6-48d937be0f8e","html_url":"https://github.com/simplyblock/autoscaling","commit_stats":null,"previous_names":["simplyblock/autoscaling"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/simplyblock/autoscaling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplyblock%2Fautoscaling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplyblock%2Fautoscaling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplyblock%2Fautoscaling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplyblock%2Fautoscaling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simplyblock","download_url":"https://codeload.github.com/simplyblock/autoscaling/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplyblock%2Fautoscaling/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31316712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-21T03:09:21.754Z","updated_at":"2026-04-02T21:25:42.423Z","avatar_url":"https://github.com/simplyblock.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NeonVM: QEMU-based virtualization API and controller for Kubernetes\n\n## Description\n\n## Getting Started\nYou’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster.\n**Note:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster `kubectl cluster-info` shows).\n\n### Install cert-manager\n\n```console\nkubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml\n```\n\n### Install NeonVM with VXLAN-based overlay network\n\n```console\nkubectl apply -f https://github.com/neondatabase/autoscaling/releases/latest/download/multus-dev.yaml\nkubectl apply -f https://github.com/neondatabase/autoscaling/releases/latest/download/whereabouts.yaml\nkubectl apply -f https://github.com/neondatabase/autoscaling/releases/latest/download/neonvm.yaml\nkubectl apply -f https://github.com/neondatabase/autoscaling/releases/latest/download/neonvm-vxlan-controller.yaml\nkubectl apply -f https://github.com/neondatabase/autoscaling/releases/latest/download/neonvm-controller.yaml\n```\n\n### Run virtual machine\n\n```console\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: vm.neon.tech/v1\nkind: VirtualMachine\nmetadata:\n  name: vm-manohar-dev\nspec:\n  powerState: Running\n  guest:\n    rootDisk:\n      image: docker.io/manoharbrm/pg16-test:dev9\n    cpus: { min: 1, use: 1, max: 64 }\n    memorySlots: { min: 1, use: 2, max: 256 }\n    memorySlotSize: 512Mi\n  disks:\n    - name: data\n      mountPath: /var/lib/postgresql/data\n      blockDevice:\n        persistentVolumeClaim:\n          claimName: my-existing-data-pvc\nEOF\n```\n\n### Attaching PVC-backed block disks\n\nAdd a disk entry with `blockDevice` under `spec.disks` to provision a PersistentVolumeClaim-backed disk. NeonVM attaches the PVC to the runner Pod, ensures it has an ext4 filesystem (creating one if the device is empty), labels it with the disk name, and mounts it inside the guest at the requested `mountPath`. For example:\n\n```yaml\nspec:\n  disks:\n    - name: data\n      mountPath: /var/lib/postgresql\n      blockDevice:\n        persistentVolumeClaim:\n          storageClassName: simplyblock-csi-sc\n          accessModes: [ReadWriteMany]\n          resources:\n            requests:\n              storage: 100Gi\n```\n\nBecause the filesystem lives on the PVC, the contents survive VM restarts without any guest-side bootstrapping.\n\nPVC expansions are detected automatically. Once the underlying claim grows, NeonVM resizes the attached virtio disk and runs `resize2fs` inside the guest so the filesystem fills the new space without manual intervention.\n\nTo reuse a PVC managed outside the VM definition, provide a claim name instead of provisioning details:\n\n```yaml\nspec:\n  disks:\n    - name: data\n      mountPath: /var/lib/postgresql\n      blockDevice:\n        persistentVolumeClaim:\n          claimName: my-existing-data-pvc\n```\n\nWhen `claimName` is set, NeonVM skips creating the PVC and simply attaches the existing volume to the VM.\n\n### Check virtual machine running\n\n```console\nkubectl get neonvm\n\nNAME        CPUS   MEMORY   POD               STATUS    AGE\nvm-debian   1      1Gi      vm-debian-8rxp7   Running   3m13s\n```\n\n### Go inside virtual machine\n\n#### SSH\n\n```sh\nkubectl exec -it $(kubectl get neonvm vm-debian -ojsonpath='{.status.podName}') -- ssh guest-vm\n```\n\n#### Pseudoterminal\n\n```console\nkubectl exec -it $(kubectl get neonvm vm-debian -ojsonpath='{.status.podName}') -- screen /dev/pts/0\n\n\u003cpress ENTER\u003e\n\nroot@neonvm:~#\nroot@neonvm:~# apt-get update \u003e/dev/null \u0026\u0026 apt-get install -y curl \u003e/dev/null\nroot@neonvm:~# curl -k https://kubernetes/version\n{\n  \"major\": \"1\",\n  \"minor\": \"25\",\n  \"gitVersion\": \"v1.25.2\",\n  \"gitCommit\": \"5835544ca568b757a8ecae5c153f317e5736700e\",\n  \"gitTreeState\": \"clean\",\n  \"buildDate\": \"2022-09-22T05:25:21Z\",\n  \"goVersion\": \"go1.19.1\",\n  \"compiler\": \"gc\",\n  \"platform\": \"linux/amd64\"\n}\n\n\u003cpress CTRL-a k to exit screen session\u003e\n```\n\n### Delete virtual machine\n\n```console\nkubectl delete neonvm vm-debian\n```\n\n### Clock synchronization\n\nWe synchronize VM clocks to host using kvm_ptp. We enable PTP clock (and the KVM related directive) on the kernel and use chrony on the VM as a server. \nYou can checkout chrony server log at `/var/log/chrony/chrony.log` and use chrony client as below:\n\n```sh\n/neonvm/bin/chronyc tracking\n/neonvm/bin/chronyc sources\n```\n\n## Local development\n\n### Run NeonVM locally\n\n#### 1. Create local cluster (with 3 nodes)\n\n```sh\nmake k3d-setup\n```\n\n#### 2. Build Linux kernel for Guests\n\n```sh\nmake kernel\n```\n\nFor more on the kernel, see [neonvm-kernel/](./neonvm-kernel/).\n\n#### 3. Build and deploy controller and VXLAN overlay network to local cluster\n\n```sh\nmake deploy\n```\n\n### Manage Virtual Machines\n\n#### 0. Build \u0026 load example images into the k8s cluster\n\n```\nmake example-vms\n```\n\n#### 1. Run virtual machine\n\n```console\nkubectl apply -f samples/vm-example.yaml\n```\n\nNB: on machines without `/dev/kvm` (e.g., on EC2 non-bare-metal), set `.spec.enableAcceleration = false`.\n\n#### 2. Check VM running\n\n```sh\nkubectl get neonvm example\n\nkubectl get neonvm example -owide\n\nkubectl describe neonvm example\n```\n\n#### 3. Check logs\n\n```sh\nVM_POD=$(kubectl get neonvm example -ojsonpath='{.status.podName}')\nkubectl logs $VM_POD\n```\n\n#### 4. Connect to the VM\n\n##### SSH\n\n```sh\nkubectl exec -it $VM_POD -- ssh guest-vm\n```\n\n##### Console\n\n```sh\nkubectl exec -it $VM_POD -- screen /dev/pts/0\n\n\u003cpress Enter to see output\u003e\n```\nto exit from console press `CTRL-a k` (see manual for `screen` tool)\n\n#### 5. Plug/Unplug CPUs in VM\n\nedit `.spec.guest.cpus.use` field by editor\n\n```sh\nkubectl edit neonvm example\n```\n\nor apply patch (set `cpus.use` to `2`)\n\n```sh\nkubectl patch neonvm example --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/guest/cpus/use\", \"value\":2}]'\n```\n\nand then check status by `kubectl get neonvm example` and inspect `/sys/devices/system/cpu` folder inside VM\n\n#### 6. Plug/Unplug Memory in VM\n\nedit `.spec.guest.memorySlots.use` field by editor\n\n```sh\nkubectl edit neonvm example\n```\n\nor apply patch (as example set `memorySlots.use` to `4`)\n\n```sh\nkubectl patch neonvm example --type='json' -p='[{\"op\": \"replace\", \"path\": \"/spec/guest/memorySlots/use\", \"value\":4}]'\n```\n\nand then check status by `kubectl get neonvm example` and inspect memory inside VM by `free -h` command\n\n#### 7. Do live migration\n\ninspect VM details to see on what node it running\n\n```sh\n$ kubectl get neonvm -owide\nNAME      CPUS   MEMORY   POD             STATUS    AGE   NODE          IMAGE\nexample   1      2Gi      example-xdw4s   Running   31s   kind-worker   vm-postgres:15-bullseye\n```\n\ntrigger live migration\n\n```sh\nkubectl apply -f samples/vm-example-migration.yaml\n```\n\ninspect migration details\n\n```sh\n$ kubectl get neonvmm -owide\nNAME      VM        SOURCE          SOURCEIP     TARGET          TARGETIP     STATUS      AGE\nexample   example   example-xdw4s   10.244.1.7   example-7ztb2   10.244.2.6   Succeeded   33s\n```\n\ninspect VM details again (look at pod name and node)\n\n```sh\n$ kubectl get neonvm -owide\nNAME      CPUS   MEMORY   POD             STATUS    AGE     NODE           IMAGE\nexample   1      2Gi      example-7ztb2   Running   4m12s   kind-worker2   vm-postgres:15-bullseye\n```\n\ninspect migration details\n\n```sh\n$ kubectl get neonvmm example -ojsonpath='{.status.info}' | jq\n{\n  \"compression\": {\n    \"compressedSize\": 44687045\n  },\n  \"downtimeMs\": 39,\n  \"ram\": {\n    \"total\": 2148278272,\n    \"transferred\": 76324646\n  },\n  \"setupTimeMs\": 2,\n  \"status\": \"completed\",\n  \"totalTimeMs\": 3861\n}\n```\n\n### Uninstall CRDs\nTo delete the CRDs from the cluster:\n\n```sh\nmake uninstall\n```\n\n### Undeploy controller\nUnDeploy the controller to the cluster:\n\n```sh\nmake undeploy\n```\n\n## How it works\nThis project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)\n\nIt uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/)\nwhich provides a reconcile function responsible for synchronizing resources untile the desired state is reached on the cluster\n\n## Roadmap\n\n- [x] Implement Webhooks for mutation and validation\n- [x] Multus CNI support\n- [x] Hot[un]plug CPUs and Memory (via resource patch)\n- [x] Live migration CRDs\n- [x] Simplify VM disk image creation from any docker image\n- [ ] ARM64 support\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimplyblock%2Fautoscaling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimplyblock%2Fautoscaling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimplyblock%2Fautoscaling/lists"}