{"id":13509560,"url":"https://github.com/virtual-kubelet/systemk","last_synced_at":"2025-10-09T07:15:12.959Z","repository":{"id":48420973,"uuid":"318590529","full_name":"virtual-kubelet/systemk","owner":"virtual-kubelet","description":"Systemk is a systemd backend for the virtual-kubelet. Instead of starting containers, you start systemd units.","archived":false,"fork":false,"pushed_at":"2021-07-27T08:55:12.000Z","size":495,"stargazers_count":161,"open_issues_count":20,"forks_count":13,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-15T01:28:32.933Z","etag":null,"topics":["crazy","kubernetes","systemd","useful","virtual-kubelet"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"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/virtual-kubelet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null}},"created_at":"2020-12-04T17:36:21.000Z","updated_at":"2025-03-26T04:11:15.000Z","dependencies_parsed_at":"2022-08-28T10:20:33.840Z","dependency_job_id":null,"html_url":"https://github.com/virtual-kubelet/systemk","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/virtual-kubelet/systemk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtual-kubelet%2Fsystemk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtual-kubelet%2Fsystemk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtual-kubelet%2Fsystemk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtual-kubelet%2Fsystemk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/virtual-kubelet","download_url":"https://codeload.github.com/virtual-kubelet/systemk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtual-kubelet%2Fsystemk/sbom","scorecard":{"id":923230,"data":{"date":"2025-08-11","repo":{"name":"github.com/virtual-kubelet/systemk","commit":"ac74c47d41e9a372dd3aab380204f47a73a6e475"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":7,"reason":"Found 23/30 approved changesets -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/e2e.yml:1","Warn: no topLevel permission defined: .github/workflows/go.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/e2e.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/e2e.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/e2e.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/e2e.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/go.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/go.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/virtual-kubelet/systemk/release.yml/main?enable=pin","Warn: goCommand not pinned by hash: .github/workflows/go.yml:27","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact tag-1612298722 not signed: https://api.github.com/repos/virtual-kubelet/systemk/releases/37260855","Warn: release artifact tag-1612298722 does not have provenance: https://api.github.com/repos/virtual-kubelet/systemk/releases/37260855"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-25T06:45:54.184Z","repository_id":48420973,"created_at":"2025-08-25T06:45:54.184Z","updated_at":"2025-08-25T06:45:54.184Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000990,"owners_count":26082972,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["crazy","kubernetes","systemd","useful","virtual-kubelet"],"created_at":"2024-08-01T02:01:09.614Z","updated_at":"2025-10-09T07:15:12.929Z","avatar_url":"https://github.com/virtual-kubelet.png","language":"Go","funding_links":[],"categories":["Go","kubernetes"],"sub_categories":[],"readme":"# Systemk: virtual kubelet for systemd\n\nThis is a virtual kubelet provider that uses systemd as its backend.\n\nEvery Linux system has systemd nowadays. By utilizing [K3s](https://k3s.io) (just one Go binary)\nand this virtual kubelet you can provision a system using the Kubernetes API. The networking is the\nhost's network, so it make sense to use this for more heavy weight (stateful?) applications. The\nfilesystem is semi hidden, but emptyDir and the like works.\n\nIt is hoped this setup allows you to use the Kubernetes API without the need to immerse yourself in\nthe (large) world of kubernetes (overlay networking, ingress objects, etc., etc.). However this\n_does_ imply networking and discovery (i.e. host) DNS is already working on the system you're\ndeploying this. How to get a system into a state it has, and can run, k3s and systemk is an open\nquestions (Ready made image? A tiny bit of config mgmt?).\n\nSystemk will use systemd to start pods as service unit(s). This uses the cgroup implementation\nsystemd has. This allows us to set resource limits, by specifying those in the unit file (copy paste\nfrom the podSpec almost). Generally there is no (real container) isolation in this setup - although\nfor disk access things are fairly contained, i.e. `/var/secrets/kubernets.io/token` will be bind\nmounted into each unit.\n\nYou basically use the k8s control plane to start linux processes. There is also no address space\nallocated to the PODs specially, you are using the host's networking.\n\n\"Images\" are referencing (Debian) packages, these will be apt-get installed. Discovering that an\ninstalled package is no longer used is hard, so this will not be done. `systemk` will reuse the unit\nfile that comes from this install, almost exclusively to find the `ExecStart` option.\nA lot of extra data is injected into it to make it work fully for systemk. If there isn't an unit\nfile (e.g. you use `bash` as the image), a unit file will be synthesized.\n\nEach scheduled unit will adhere to a naming scheme so `systemk` knows which ones are managed by it.\n\n## Is This Useful?\n\nLikely. I personally consider this useful enough to manage a small farm of machines. Say you\nadminister 200 machines and you need saner management and introspection than config management\ncan give you? I.e. with `kubectl` you can find which machines didn't run a DNS server, with\n*deployments* you can more safely push out upgrades, with \"insert favorite Kubernetes feature here\"\nyou can do canarying.\n\nMonitoring, for instance, only requires prometheus to discover the pods via the Kubenetes API,\nvastly simplifying that particular setup. See\n[prometheus.yaml](https://github.com/virtual-kubelet/systemk/blob/main/k3s/prometheus.yaml) for a\ncomplete, working, setup that discovers running Pods and scrapes them. The prometheus config is\n*just* `kubernetes_sd_configs`.\n\nCurrently I manage 2 (Debian) machines and this is all manual - i.e.: login, apt-get upgrade, fiddle\nwith config files etc. It may turn of that k3s + systemk is a better way of handling even *2* machines.\n\nNote that getting to the stage where this all runs, is secured and everything has the correct TLS\ncerts (that are also rotated) is an open question. See https://github.com/miekg/systemk/issues/39 for\nsome ideas there.\n\n## Current Status\n\nMultiple containers in a pod can be run and they can see each others storage. Creating, deleting,\ninspecting Pods all work. Higher level abstractions (replicaset, deployment) work too. Init\nContainers are also implemented.\n\nEmptyDir/configMap/hostPath and Secret are implemented, all, except hostPath, are backed by a\nbind-mount. The entire filesystem is made available, but read-only, paths declared as volumeMounts\nare read-only or read-write depending on settings. When configMaps and Secrets are mutated the new\ncontents are updated on disk. These directories are set up in\n`/var/run/{emptydirs, secrets, configmaps}`.\n\nRetrieving pod logs also works, but setting up TLS is not automated.\n\nHas been tested on:\n\n* ubuntu 20.04 and 18.04\n* arch (maybe?)\n\n## Building\n\nUse `go build` in the top level directory, this should give you a `systemk` binary which is the virtual\nkubelet. Note you'll need to have libsystemd-dev (deb) or systemd-devel (rpm) installed to build\nsystemk and you be able to build with CGO.\n\n## Design\n\nPods can contain multiple containers; each container is a new unit and tracked by systemd. The named\nimage is assumed to be a *package* and will be installed via the normal means (`apt-get`, etc.). If\nsystemk is installing the package the official system unit will be disabled; if the package already\nexists we leave the existing unit alone. If the install doesn't come with a unit file (say you\ninstall `zsh`) we will synthesize a small service unit file; for this to work the podSpec need to\n(at) least define a command to run.\n\nCreatePod call we call out to systemd to create a unit per container in the pod. Each unit will\nbe named `systemk.\u003cpod-namespace\u003e.\u003cpod-name\u003e.\u003cimage-name\u003e.service`. If a command is given it will\nreplace the first word of `ExecStart` and leave any options there. If `args` are also given the\nentire `ExecStart` is replaced with those. If only `args` are given the command will remain and only\nthe options/args will be replaced.\n\nWe store a bunch of k8s meta data inside the unit in a `[X-kubernetes]` section. Whenever we want to\nknow a pod state systemk will query systemd and read the unit file back. This way we know the status\nand have access to all the meta data, like pod UID and if the unit is an init container.\n\n### Specifying Images\n\nIn general the image you specify is a (distro) package, i.e. `bash-$version.deb`. But there are\nalternatives that can be used and give you some flexibility.\n\n#### Fetching Image Remotely\n\nIf the image name starts with `https://` it is assumed an URL and the package is fetched from there\nand installed. The image name is the first string up until the `_` in the package name:\n`https://example.org/tmp/coredns_1.7.1-bla_amd64.deb` will download the package from that URL and\n`coredns` will be the package name.\n\n#### Binary Exists in File System\n\nIf the image name starts with a `/` it's assumed to be a path to a binary that exists on the system,\nnothing is installed in that case. Basically this tells systemk that the image is not used. This can\nserve as documentation. It's likely command and/or args in the podspec will reference the same path.\n\n### Addresses\n\nAddresses are configured with one the systemk command line flags: `--node-ip` and\n`--node-external-ip`, these may be IPv4 or IPv6. In the future this may get expanded into allow both\n(i.e. dual stack support). The primary Pod address will be the value from `--node-external-ip`.\n\nIf `--node-ip` is not given, systemk will try to find a RFC 1918 address on the interfaces and uses the\nfirst one found.\n\nIf `--node-external-ip` is not given, systemk will try to find a non-RFC 1918 address on the\ninterfaces and uses the first one found.\n\nIf after all this one of the values is still not found, the other existing value will be copied, i.e\ninternal == external in that case. If both were empty systemk exits with a fatal error.\n\n### Environment Variables\n\nThe following environment variables are made available to the units:\n\n* `HOSTNAME`, `KUBERNETES_SERVICE_PORT` and `KUBERNETES_SERVICE_HOST` (same as the kubelet).\n* `SYSTEMK_NODE_INTERNAL_IP` the internal IP address.\n* `SYSTEMK_NODE_EXTERNAL_IP` the external IP address.\n\n### Using username in securityContext\n\nTo specify an *username* in a securityContext you need to use the `windowsOptions`:\n~~~\nspec:\n  securityContext:\n    windowsOptions:\n      runAsUserName: \"prometheus\"\n~~~\nThe primary group will be found by systemk and both a `User` and `Group` will be injected into the\nunit file. The files created on disk for the configMap/secrets/emptyDir will be made of the same\nuser/group.\n\n### Running Without Root Permissions\n\nThis is not possible, the tiniest thing we need is `BindPaths` which is not allowed when not running\nas root (or `CAP_SYS_ADMIN`). This means `systemk` needs close to full root permission to run.\n\n### Limitations\n\nBy using systemd and the host's network stack we have weak isolation between pods, i.e. no more\nthan process isolation. Starting two pods that use the same port is guaranteed to fail for one.\nTo expand on this, everything is run as if `.spec.hostNetwork: true` is specified. Port clashes\nare (probably?) more likely for health check ports. Two pods using the same (health check) port\nthus can't schedule on the same machine. We have some ideas to get around this (like generating\nan environment variable with a unique port number (or using `$RANDOM`) that can be used for health\nchecking, but are also open to suggestions, including not doing anything.\n\n## Use with K3S\n\nDownload k3s from it's releases on GitHub, you just need the `k3s` binary. Use the `k3s/k3s` shell\nscript to start it - this assumes `k3s` sits in \"~/tmp/k3s\". The script starts k3s with basically\n*everything* disabled.\n\nCompile `systemk` and start it with.\n\n~~~\nsudo ./systemk --kubeconfig ~/.rancher/k3s/server/cred/admin.kubeconfig --disable-taint\n~~~\n\nWe need root to be allowed to install packages.\n\nNow a `k3s kubcetl get nodes` should show the virtual kubelet as a node:\n\n~~~\nNAME    STATUS   ROLES   AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE            KERNEL-VERSION     CONTAINER-RUNTIME\ndraak   Ready    agent   6s    v1.18.4   \u003cnone\u003e        \u003cnone\u003e        Ubuntu 20.04.1 LT   5.4.0-53-generic   systemd 245 (245.4-4ubuntu3.3)\n~~~\n\n`draak` is my machine's name. You can now try to schedule a pod: `k3s/kubelet apply -f\nk3s/uptimed.yaml`.\n\nLogging works, but due to TLS, is a bit fiddly, you need to start `systemk` with --certfile and\n--keyfile to make the HTTPS endpoint happy (enough). Once that's done you can get the logs with:\n\n~~~\n% ./kubectl logs --insecure-skip-tls-verify-backend=true uptimed\n-- Logs begin at Mon 2020-08-24 09:00:18 CEST, end at Thu 2020-11-19 15:40:02 CET. --\nnov 19 12:12:27 draak systemd[1]: Started uptime record daemon.\nnov 19 12:14:44 draak uptimed[15245]: uptimed: no useable database found.\nnov 19 12:14:44 draak systemd[1]: Stopping uptime record daemon...\nnov 19 12:14:44 draak systemd[1]: systemk.default.uptimed.uptimed.service: Succeeded.\nnov 19 12:14:44 draak systemd[1]: Stopped uptime record daemon.\nnov 19 13:38:54 draak systemd[1]: Started uptime record daemon.\nnov 19 13:39:26 draak systemd[1]: Stopping uptime record daemon...\nnov 19 13:39:26 draak systemd[1]: systemk.default.uptimed.uptimed.service: Succeeded.\n~~~\n\n### Prometheus discovering targets to Scrape\n\nThe includes manifests `k3s/prometheus.yaml` and `k3s/uptimed.yaml` install a prometheus with k8s\nsupport and the uptimed. This allows prom to find the open ports for uptimed and will start scraping\nthose for metrics (uptimed doesn't have metrics, but that's a minor detail). Here is the status of\nprom finding those targets and trying to scrape:\n\n![Prometheus running as systemd unit finding targets](img/prom.jpeg)\n\n### Debian/Ubuntu\n\n1. Install *k3s* and compile the virtual kubelet.\n\nI'm using `uptimed` as a very simple daemon that you (probably) haven't got installed, so we can\ncheck the entire flow.\n\n3. `./k3s/kubectl apply -f uptimed.yaml`\n\nThe above *should* yield:\n\n~~~\nNAME      READY   STATUS    RESTARTS   AGE\nuptimed   1/1     Running   0          7m42s\n~~~\n\nYou can then delete the pod.\n\n## Testing\n\n### Set-up Node authentication\n\n`systemk` impersonates a Node and, as such, can identify itself through a TLS\nclient certificate.\nLet's set that up.\n\n1. Install `cert-manager`, required to provision a TLS certificate\nthat will later be used when authenticating `systemk` as a Kubernetes Node.\n\n    ```bash\n    kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml\n    ```\n\n1. Expose private CA resources as a Secret, a requirement for the next step.\n\n    1. If using `kind`:\n\n       ```bash\n       docker exec -e KUBECONFIG=/etc/kubernetes/admin.conf kind-control-plane sh -c \\\n          'kubectl -n cert-manager create secret tls priv-ca \\\n          --cert=/etc/kubernetes/pki/ca.crt \\\n          --key=/etc/kubernetes/pki/ca.key'\n       ```\n\n   1. If using `minikube`:\n\n      ```bash\n      minikube ssh\n\n      sudo /var/lib/minikube/binaries/v1.20.1/kubectl \\\n        --kubeconfig /etc/kubernetes/admin.conf \\\n        -n cert-manager create secret tls priv-ca \\\n        --cert=/var/lib/minikube/certs/ca.crt \\\n        --key=/var/lib/minikube/certs/ca.key\n\n      exit\n      ```\n\n1. Create a cluster-wide certificate issuer that re-uses the cluster PKI.\n\n    ```bash\n    cat \u003c\u003cEOF | kubectl apply -f -\n    apiVersion: cert-manager.io/v1\n    kind: ClusterIssuer\n    metadata:\n      name: priv-ca-issuer\n    spec:\n      ca:\n        secretName: priv-ca\n    EOF\n\n    kubectl wait --for=condition=Ready --timeout=1m clusterissuer priv-ca-issuer\n    ```\n\n1. Create a certificate signing request that `cert-manager` can sign with the\n   CA setup during your Kubernetes cluster bootstrap.\n\n    ```bash\n    NODENAME=systemk\n    cat \u003c\u003cEOF | kubectl apply -f -\n    apiVersion: cert-manager.io/v1\n    kind: Certificate\n    metadata:\n      name: $NODENAME\n      namespace: default\n    spec:\n      secretName: $NODENAME-tls\n      duration: 8760h # 1 year\n      renewBefore: 4380h # 6 months\n      subject:\n        organizations:\n        - system:nodes\n      commonName: system:node:$NODENAME\n      issuerRef:\n        name: priv-ca-issuer\n        kind: ClusterIssuer\n    EOF\n\n    kubectl wait --for=condition=Ready --timeout=1m certificate $NODENAME\n    ```\n\n1. Initialize a _kubeconfig_ file `systemk` will rely on.\n\n   1. If using `kind`:\n\n      ```bash\n      rm -f $NODENAME.kubeconfig\n      kind get kubeconfig \u003e $NODENAME.kubeconfig\n\n      kubectl --kubeconfig=$NODENAME.kubeconfig config unset contexts.kind-kind\n      kubectl --kubeconfig=$NODENAME.kubeconfig config unset users.kind-kind\n      ```\n\n   1. If using `minikube`:\n\n      ```bash\n      rm -f $NODENAME.kubeconfig\n      KUBECONFIG=$NODENAME.kubeconfig minikube update-context\n\n      kubectl --kubeconfig=$NODENAME.kubeconfig config unset contexts.minikube\n      kubectl --kubeconfig=$NODENAME.kubeconfig config unset users.minikube\n      ```\n\n1. Extract the signed certificate and respective private key, and populate the\n   _kubeconfig_ file, appropriately.\n\n   ```bash\n   kubectl get secret $NODENAME-tls -o jsonpath='{.data.tls\\.crt}' | base64 -d \u003e $NODENAME.crt\n   kubectl get secret $NODENAME-tls -o jsonpath='{.data.tls\\.key}' | base64 -d \u003e $NODENAME.key\n\n   kubectl --kubeconfig=$NODENAME.kubeconfig config set-credentials $NODENAME \\\n    --client-certificate=$NODENAME.crt \\\n    --client-key=$NODENAME.key\n\n   kubectl --kubeconfig=$NODENAME.kubeconfig config set-context $NODENAME --cluster=minikube --user=$NODENAME\n   kubectl --kubeconfig=$NODENAME.kubeconfig config use-context $NODENAME\n   ```\n### Running the Node\n\n1. Allow `systemk` to view ConfigMaps and Secrets across the cluster.\n   This is far from ideal but works for now.\n\n   ```bash\n   kubectl create clusterrolebinding $NODENAME-view --clusterrole=system:node --user=system:node:$NODENAME\n   ```\n\n1. Finally, start `systemk`.\n\n   ```bash\n   NODENAME=systemk\n   ./systemk --kubeconfig=$NODENAME.kubeconfig --nodename=$NODENAME\n   ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirtual-kubelet%2Fsystemk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvirtual-kubelet%2Fsystemk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirtual-kubelet%2Fsystemk/lists"}