{"id":13443002,"url":"https://github.com/jpetazzo/shpod","last_synced_at":"2025-03-20T15:31:47.601Z","repository":{"id":35739955,"uuid":"218857507","full_name":"jpetazzo/shpod","owner":"jpetazzo","description":"Container image to get a consistent training environment to work on Kubernetes.","archived":false,"fork":false,"pushed_at":"2024-06-21T16:53:55.000Z","size":44,"stargazers_count":159,"open_issues_count":1,"forks_count":56,"subscribers_count":9,"default_branch":"main","last_synced_at":"2024-08-01T03:42:31.766Z","etag":null,"topics":["kubernetes","pod"],"latest_commit_sha":null,"homepage":"","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jpetazzo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2019-10-31T20:37:41.000Z","updated_at":"2024-07-26T17:28:33.000Z","dependencies_parsed_at":"2023-11-20T23:40:56.720Z","dependency_job_id":null,"html_url":"https://github.com/jpetazzo/shpod","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpetazzo%2Fshpod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpetazzo%2Fshpod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpetazzo%2Fshpod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpetazzo%2Fshpod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jpetazzo","download_url":"https://codeload.github.com/jpetazzo/shpod/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221772633,"owners_count":16878145,"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","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":["kubernetes","pod"],"created_at":"2024-07-31T03:01:54.644Z","updated_at":"2025-03-20T15:31:47.594Z","avatar_url":"https://github.com/jpetazzo.png","language":"Dockerfile","funding_links":[],"categories":["Dockerfile","Shell"],"sub_categories":[],"readme":"# shpod\n\n**⚠️ Please listen carefully, as our ~~menu options~~\ninstallation instructions have changed.**\n\n~~Old instructions: `curl https://shpod.in | sh`~~\n\nNew instructions: use the Helm chart!\n\nTo get a shell in your Kubernetes cluster, with `cluster-admin` privileges:\n\n```bash\nhelm upgrade --install --repo https://shpod.in/ shpod shpod \\\n  --set rbac.cluster.clusterRoles=\"{cluster-admin}\"\nkubectl wait deployment shpod --for=condition=Available\nkubectl exec -ti deployment/shpod -- login -f k8s\n```\n\n## What's this?\n\nShpod (\"Shell in a pod\") is a tool to get a shell session with a ton\nof tools useful when working with containers, Docker, and Kubernetes.\n\nIt's composed of two parts:\n\n- a container image holding all the tools,\n- a Helm chart making it easy to deploy it on Kubernetes.\n\nIts goal is to provide a normalized environment, to go\nwith the training materials at https://container.training/,\nso that you can get all the tools you need regardless\nof your exact Kubernetes setup.\n\n\n## The shpod image\n\nIt's available as `jpetazzo/shpod` or `ghcr.io/jpetazzo/shpod`.\n\nIt's based on Alpine, and includes:\n\n- ab (ApacheBench)\n- bash\n- bento\n- crane\n- curl\n- Docker CLI\n- Docker Compose\n- envsubst\n- fzf\n- git\n- gron\n- Helm\n- jid\n- jq\n- kubectl\n- kubectx + kubens\n- kube-linter\n- kube-ps1\n- kubeseal\n- kustomize\n- ngrok\n- popeye\n- regctl\n- ship\n- skaffold\n- skopeo\n- SSH\n- stern\n- tilt\n- tmux\n- yq\n- ytt\n\nIt also includes completion for most of these tools.\n\nWhen this image starts, it will behave differently depending on whether\nit has a pseudo-terminal or not.\n\nIf it has a pseudo-terminal, it will spawn a shell.\nYou can access that shell by attaching to the container,\nwithout having to bother with networking or password configuration.\nYou can see that mode in action by running one of the following commands:\n\n```bash\ndocker run -ti jpetazzo/shpod\nkubectl run --rm -ti shpod --image jpetazzo/shpod\n```\n\nIf it does not have a pseudo-terminal, it will run an SSH server.\nDepending on the values of some environment variables, it will\nuse a provided password or generate one, or use SSH public key\nauthentication (see below, \"SSH access configuration\").\n\nYou can see that mode in action by running the following command:\n\n```bash\ndocker run jpetazzo/shpod\n```\n\nHowever, that mode will likely be more useful on Kubernetes, for instance:\n```bash\nkubectl create deployment shpod --image jpetazzo/shpod\nkubectl expose deployment shpod --port 22 --type=NodePort\nkubectl logs deployment/shpod\n```\n\nThe last command should show you the password that was generated\nfor the `k8s` user:\n\n```\nGenerating public/private rsa key pair.\nYour identification has been saved in /etc/ssh/ssh_host_rsa_key\nYour public key has been saved in /etc/ssh/ssh_host_rsa_key.pub\nThe key fingerprint is:\nSHA256:xEZav2W/XkJ45KaZvxVLNfudttmVwzvAbd8v/b8jkA0 root@shpod-5965cbcfc9-f5p8m\nThe key's randomart image is:\n+---[RSA 3072]----+\n|        o        |\n|       = .       |\n|      . + . o ...|\n|       o   E =  +|\n|        S . * B+ |\n|           o @o+B|\n|            = =OO|\n|             +o*@|\n|              =B%|\n+----[SHA256]-----+\nEnvironment variable $PASSWORD not found. Generating a password.\nPASSWORD=BlVweGRkEf1PQNdrhpjg\nchpasswd: password for 'k8s' changed\nServer listening on 0.0.0.0 port 22.\nServer listening on :: port 22.\n```\n\nIn both cases, you can also access shpod by executing a new shell\nin the existing container.\n\nWith Docker:\n```bash\ndocker exec -ti \u003ccontainer-id\u003e login -f k8s\n```\n\nWith Kubernetes:\n```bash\nkubectl exec -ti deployment/shpod -- login -f k8s\n```\n\n\n## Multi-arch support\n\nShpod supports both Intel and ARM 64 bits architectures. The Dockerfile\nin this repository should be able to support other architectures fairly\neasily. If a given tool isn't available on the target architecture,\na dummy placeholder will be installed instead.\n\n\n## SSH access configuration\n\nThe user is always `k8s` - this is currently hard-coded.\n\nIt is possible to log in either by using a password, or SSH public key\nauthentication.\n\nIf the `$PASSWORD` variable is set, it will define the password for\nthe `k8s` user.\n\nIf the `$AUTHORIZED_KEYS` variable is set, it should hold one or multiple\nSSH public keys (one per line), and these keys will be added to the\n`~/.ssh/authorized_keys` file.\n\nIf neither `$PASSWORD` nor `$AUTHORIZED_KEYS` are set, then a random\npassword will be generated. By default, that password will be 20 characters\nlong, using digits, lowercase, and uppercase letters.\n\nIt is possible to change the length of the generated password by setting\nthe variable `$GENERATE_PASSWORD_LENGTH`. If that variable is set to `0`,\nno password will be generated.\n\n⚠️ When a password is generated, it is displayed on stdout. This means\nthat if someone has access to the logs of the container, they will be\nable to see that password.\n\n⚠️ If the container restarts for any reasons, a new password will be\ngenerated. This is considered to be a feature.\n\nWhen using shpod as part of a larger system, it is advised to set the\npassword (or the SSH keys) to avoid both warnings above.\n\n\n## Kubernetes permissions\n\nShpod is meant to be used inside Kubernetes clusters. Once you are\nrunning inside shpod, Kubernetes commands (like `kubectl` or `helm`)\nwill use \"in-cluster configuration\"; in other words, these commands\nwill use the ServiecAccount of the Pod that runs shpod.\n\nBy default, on most clusters, that ServiceAccount won't have much\npermissions, meaning that you will get errors like the following one:\n\n```console\n$ kubectl get pods\nError from server (Forbidden): pods is forbidden: User \"system:serviceaccount:default:default\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"\n```\n\nIf you want to use Kubernetes commands within shpod, you need\nto give permissions to that ServiceAccount.\n\nAssuming that you are running shpod in the `default` namespace\nand with the `default` ServiceAccount, you can run the following\ncommand to give `cluster-admin` privileges (=all privileges) to\nthe commands running in shpod:\n\n```bash\nkubectl create clusterrolebinding shpod \\\n        --clusterrole=cluster-admin \\\n        --serviceaccount=default:default\n```\n\n\n## Special handling of kubeconfig\n\nIf you have a ConfigMap named `kubeconfig` in the Namespace\nwhere shpod is running, it will extract the first file from\nthat ConfigMap and use it to populate `~/.kube/config`.\n\nThis lets you inject a custom kubeconfig file into shpod.\n\n\n## Helm chart\n\nSince November 2024, shpod also has a Helm chart!\n\nThis Helm chart offers the following features:\n\n- enable or disable the SSH server (depending on your needs)\n- put the `k8s` user home directory on a Persistent Volume\n- list Roles and ClusterRoles to bind to the ServiceAccount\n\nHere's an example of how to use it:\n\n```bash\nhelm upgrade --install --repo https://shpod.in/ shpod shpod \\\n  --set service.type=NodePort \\\n  --set resources.requests.cpu=0.1 \\\n  --set resources.requests.memory=500M \\\n  --set resources.limits.cpu=1 \\\n  --set resources.limits.memory=500M \\\n  --set persistentVolume.enabled=true \\\n  --set \"rbac.cluster.clusterRoles={cluster-admin}\" \\\n  --set ssh.authorized_keys=\"$(cat ~/.ssh/*.pub)\" \\\n  #\n```\n\n\n## I don't like Helm charts!\n\nYou can also use the following YAML manifest:\n\n```bash\nkubectl apply -f https://shpod.in/shpod.yaml\n```\n\nThen attach to the shpod pod:\n\n```bash\nkubectl attach --namespace=shpod -ti shpod\n```\n\nBut you really should use the Helm chart instead.\n\n\n## Why should I use the Helm chart?\n\nI'm using shpod when teaching Kubernetes classes. I deploy a Kubernetes\ncluster for each student, and they access the cluster by connecting with\nSSH. In some cases, I deploy the clusters with `kubeadm` on top of \"raw\"\nVMs, and the students connect directly to the nodes. In some cases, I'm\nusing managed Kubernetes clusters, and SSH access to the nodes may or\nmay not be possible; in any case, it will require different steps for\neach cloud provider. To simplify things, I built shpod, and use it to\nrun an SSH server that the students connect to.\n\nThis approach works great for most Kubernetes classes, but there are a\nfew scenarios that are problematic; specifically, when the Node running\nshpod is starved for resources, the shpod Pod might get evicted. This\ncauses all the files in the container to be deleted, which is not great\nwhen it happens during a class.\n\nThe solution to that problem has multiple layers:\n\n1. Specify resource requests and limits, in particular for memory, to\n   avoid the pod being evicted by memory pressure on the node.\n2. Place the `k8s` user home directory on a Persistent Volume, so that\n   the content of the home directory isn't lost if the Pod gets evicted\n   anyway or the underlying Node crashes or gets removed for any reason.\n3. Make that Persistent Volume optional, so that shpod still works on\n   clusters that don't have a Storage Class providing dynamic volume\n   provisioning. In that case, fall back gracefully to an `emptyDir`\n   volume, to prevent pod eviction by `kubectl drain` or by the cluster\n   autoscaler, and to persist files across container restarts.\n\nThe Helm chart lets you pick easily which configuration works best for\nyou: with or without the SSH server, with or without a password or SSH\npublic keys, with or without a Persistent Volume, with or without\nresource requests and limits...\n\n## Experimental stuff\n\nYou can enable code-server (basically \"VScode used from a browser\")\nand expose it over a `NodePort` like so:\n\n```bash\nhelm upgrade --install --repo https://shpod.in/ shpod shpod \\\n  --set codeServer.enabled=true \\\n  --set persistentVolume.enabled=true \\\n  --set rbac.cluster.clusterRoles=\"{cluster-admin}\" \\\n  --set resources.requests.cpu=0.1 \\\n  --set resources.requests.memory=500M \\\n  --set resources.limits.cpu=1 \\\n  --set resources.limits.memory=500M \\\n  --set service.type=NodePort \\\n  --set ssh.password=codeserver.support.is.beta.and.will.break\nkubectl wait deployment shpod --for=condition=Available\n```\n\nThis is super experimental; I'd like to refactor the image and the\nHelm chart before going further. So if you use this, you should expect\nit to break in the near future.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpetazzo%2Fshpod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjpetazzo%2Fshpod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpetazzo%2Fshpod/lists"}