{"id":19857893,"url":"https://github.com/googlecontainertools/kubehost","last_synced_at":"2025-10-09T12:36:33.622Z","repository":{"id":52444330,"uuid":"151144633","full_name":"GoogleContainerTools/kubehost","owner":"GoogleContainerTools","description":"Expose web services directly on GKE nodes during development.","archived":false,"fork":false,"pushed_at":"2018-10-03T17:40:14.000Z","size":14,"stargazers_count":115,"open_issues_count":11,"forks_count":16,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-13T12:50:40.235Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","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/GoogleContainerTools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-01T19:14:50.000Z","updated_at":"2024-04-06T02:46:36.000Z","dependencies_parsed_at":"2022-08-18T19:02:31.860Z","dependency_job_id":null,"html_url":"https://github.com/GoogleContainerTools/kubehost","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/GoogleContainerTools/kubehost","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleContainerTools%2Fkubehost","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleContainerTools%2Fkubehost/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleContainerTools%2Fkubehost/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleContainerTools%2Fkubehost/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GoogleContainerTools","download_url":"https://codeload.github.com/GoogleContainerTools/kubehost/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleContainerTools%2Fkubehost/sbom","scorecard":{"id":58545,"data":{"date":"2025-08-11","repo":{"name":"github.com/GoogleContainerTools/kubehost","commit":"71d2a859cfba7172351200f2f0debb4d900c47e8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"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":"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":"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":"Code-Review","score":5,"reason":"Found 1/2 approved changesets -- score normalized to 5","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":-1,"reason":"no workflows found","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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"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":"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":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 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"}},{"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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"}}]},"last_synced_at":"2025-08-15T01:13:46.764Z","repository_id":52444330,"created_at":"2025-08-15T01:13:46.764Z","updated_at":"2025-08-15T01:13:46.764Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001432,"owners_count":26083078,"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":[],"created_at":"2024-11-12T14:20:07.270Z","updated_at":"2025-10-09T12:36:33.591Z","avatar_url":"https://github.com/GoogleContainerTools.png","language":"Shell","readme":"# kubehost\n\nKubehost helps you expose services directly on nodes of your\nGoogle Kubernetes Engine (GKE) cluster.\n\nThe common way to expose a service and get an external IP is\n`kubectl expose \u003cdeployment\u003e --type=LoadBalancer\"`, which will expose\nyour deployment on a production-grade Google Cloud Load Balancer.\nSometimes you just want to expose a service on your VM directly, like\nduring development where uptime and reliability are not as important.\nThat's where Kubehost comes in.\n\nKubehost uses existing features of GKE to expose your service directly\nonto one of the VMs in your cluster, by creating a Pod that runs on\nthe VM's network and forwards traffic to your in-cluster (ClusterIP)\nservice, and creating firewall rules to permit external traffic.\nWhile you could do this manually, Kubehost takes the toil out of\nmanaging this configuration by automating the necessary actions.\n\n\u003cbr\u003e\n\n\u003e ### :warning: For development use only\n\u003e kubehost is NOT designed for production use! Nodes in GKE\n\u003e are designed to be redundant, meaning they can fail.\n\u003e When the node on which your service is exposed via kubehost fails or\n\u003e is upgraded, your service will experience several minutes of downtime.\n\u003e By comparison, if you use a production-grade Google Cloud Load\n\u003e Balancer (and you have enough replicas of your Pod spread over\n\u003e multiple nodes with properly implemented health and readiness checks)\n\u003e then a node can fail with only minimal impact to the availability of\n\u003e your service. At any time you can upgrade to a Google Cloud Load\n\u003e Balancer with the `kubehost upgrade` command.\n\n## Installation\n\n`kubehost` is a bash script. To install, clone this repository and add\nit to your `$PATH`, or copy `kubehost` to your `/usr/local/bin/`.\n\nYou may need to set the executable permission, i.e. `chmod +x kubehost`. \n\n## Configuration\n\nBefore using `kubehost`, you need to ensure both `gcloud` and `kubectl`\nare configured with your desired project \u0026 cluster.\n\n1. run `gcloud init` to select your account, project and region\n   containing the GKE cluster.\n2. run \n[get-credentials](https://cloud.google.com/sdk/gcloud/reference/container/clusters/get-credentials)\n   to configure `kubectl`.\n\n## Exposing a Deployment with kubehost\n\n1. Create your deployment like normal.\n2. Create a ClusterIP service for your deployment (this is the default\n   service type, so no need to specify any type), **on your desired\n   external port**.\n3. Run `kubehost bind ${SERVICE}`, where `${SERVICE}` is the name of\n   the Kubernetes service you created at step 2.\n\nWhat this does is create some \"glue\" in the form of a hostPort\ndeployment so that your service is bound to port you specified in the\nservice on your node's external IP (read \"under the hood\" for a longer\ntechnical description). It also opens the necessary GCP firewall rules.\n\nTo undo, `kubehost unbind ${SERVICE}`\n\nComplete example:\n\n```bash\nkubectl run hello --image gcr.io/google-samples/hello-app:1.0 --port 8080\nkubectl expose deployment hello --port 80 --target-port 8080 --name hello-service\nkubehost bind hello-service\n```\n\nCleanup:\n```bash\nkubehost unbind hello-service\nkubectl delete deployment hello\nkubectl delete service hello-service\n```\n\n## Switching between hostPort and a Load Balancer\n\n### Upgrading to a Load Balancer from hostPort\n\nIs your app ready for prime time? Remove the hostPort Pod \"glue\", and\nconvert your Service into one backed by a\n[Google Cloud Load Balancer](https://cloud.google.com/load-balancing/)\nwith one simple command:\n\n```bash\nkubehost upgrade ${SERVICE}\n```\n\nWhere `${SERVICE}` is the name of your Cluster IP service.\n\n### Downgrading a Load Balancer to hostPort\n\nDid you already expose your service with a Load Balancer and found it's\nmore than you needed?  Convert it to an internal ClusterIP service,\nand expose it on a host in one command with:\n\n```bash\nkubehost downgrade ${SERVICE}\n```\n\nWhere `${SERVICE}` is the name of your Kubernetes service of type\nLoadBalancer.\n\n## Limitations\n\n* Kubehost currently works with services that have a single port. If you\n  need to expose two ports, create two ClusterIP services.\n* Kubehost is not designed for production usage, see the note above.\n* Kubehost doesn't give you a static IP. The IP address of node may\n  change which will affect your service. You can create a static IP\n  and use the [kubeIP](https://github.com/doitintl/kubeIP) operator to\n  keep it assigned through node maintenance events.\n\n## Under the Hood\n\nWhat Kubehost is doing when you call `bind` is creating\na Kubernetes Deployment with a single replica of a Pod that uses\nhostPort to bind onto the host's network interface. The container in\nthis Pod forwards traffic to your ClusterIP service.\n\nWhile you could instead change your deployment to use hostPort directly\n we think this approach is superior, as:\n\n1. It's closer to the production Kubernetes experience where deployments\n   have a matching service to receive traffic.\n2. It's easier to switch between this and a production setup by\n   changing the Service type to LoadBalancer, and removing the hostPort\n    deployment (and vice-versa) – no need to modify your application\n   deployment.\n3. Your deployment's replica count isn't limited by available ports.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecontainertools%2Fkubehost","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgooglecontainertools%2Fkubehost","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecontainertools%2Fkubehost/lists"}