Merge in upstream refactor for multiplatform awesomesauce (#42)

* Changes stern to point to stern/stern

* ♻️ Update Stern to use stern/stern; get it from the GHCR image; update curl commands

* Update README to mention Bret's fork which supports ARM

* ♻️ Bump up versions and fix krew missing from PATH

Fixes #12

* Add alias k=kubectl + completion

Closes #11

* Update shpod.yaml

Remove `imagePullPolicy`; it will default to `Always` since we're using the `:latest` tag.

* ✏️  Change default editor (for kubectl edit) to vim

*  Update krew install URL

* ⚙️  Add GHA workflow to build+push to GHCR and Docker Hub

* 🏭️ Refactor Dockerfile to log as non-root

Multiple improvements here:
- start a shell with the k8s user instead of root
- when running without a tty, start an SSH server instead of a login shell
- move shell setup to bash_profile instead of Dockerfile
- add a helper script to set up tailhist
- add motd support

*  Add 'tree' and 'kustomize'

*  Upgrade to Compose v2 and add completion for a bunch of tools

* 🔧 Minor fixes and tweaks

*  Add regclient tools (regbot, regctl, regsync)

* 📃 Generate kubeconfig + update docs

*  Add kube-linter

* ♻️  Refactor Dockerfile to leverage BuildKit parallelism

* 🧹 Build httping instead of using a sketchy binary

* 🧹 Move jid version to an env var

* 🏭️ Rewrite Dockerfile to support multi-arch and cross-compilation

*  Add Docker CLI

* ♻️  Move version numbers to their individual build stage for better caching

* 🐞 Fix multi-arch support for krew

* 📃 Update documentation

*  Add crane, ngrok, and skopeo

*  Add yq and switch versions to ARG instead of ENV

Thanks @soulshake for the suggestion!

*  Update kubeseal

* 🐞 Fix kubeconfig download logic

*  Remove fftw (it's huge and doesn't bring much benefit to httping)

* 🐞 Tiny typo fix in motd

*  Add k9s; rollback kubeseal version

* 📃 Add info to install packages in motd

* ✂️  Remove skopeo (it's rarely used and it's juse one 'apk add' away)

*  Add iputils so that ping runs without sudo

* 🔑 Increase MaxAuthTries in SSH for folks with many keys

* push on pr

* auth on pr's

* only latest if on default branch

Co-authored-by: onlinejudge95 <onlinejudge95@gmail.com>
Co-authored-by: Jérôme Petazzoni <jerome.petazzoni@gmail.com>
This commit is contained in:
Bret Fisher
2022-01-14 17:30:06 -05:00
committed by GitHub
parent 6e0b6797bd
commit 097e3df462
10 changed files with 505 additions and 183 deletions

View File

@@ -53,14 +53,12 @@ jobs:
${{ runner.os }}-buildx- ${{ runner.os }}-buildx-
- -
name: Login to DockerHub name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1 uses: docker/login-action@v1
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- -
name: Login to GHCR name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v1 uses: docker/login-action@v1
with: with:
registry: ghcr.io registry: ghcr.io
@@ -78,7 +76,8 @@ jobs:
flavor: | flavor: |
latest=false latest=false
tags: | tags: |
type=raw,value=latest type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
type=ref,event=pr,prefix=pr
- -
# this will build the images, once per platform, # this will build the images, once per platform,
# then push to both Docker Hub and GHCR # then push to both Docker Hub and GHCR
@@ -87,12 +86,12 @@ jobs:
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
# had to remove linux/arm/v7 due to missing docker image # had to remove linux/arm/v7 due to missing docker image
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64,linux/arm/v7
builder: ${{ steps.buildx.outputs.name }} builder: ${{ steps.buildx.outputs.name }}
cache-from: type=local,src=/tmp/.buildx-cache cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new cache-to: type=local,dest=/tmp/.buildx-cache-new
# don't push during a pull_request, only build # for an approved pull_request, only push pr-specific tags
push: ${{ github.event_name != 'pull_request' }} push: true
tags: ${{ steps.docker_meta.outputs.tags }} tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }} labels: ${{ steps.docker_meta.outputs.labels }}
- -

View File

@@ -1,188 +1,232 @@
FROM golang:alpine AS jid FROM --platform=$BUILDPLATFORM golang:alpine AS builder
RUN apk add git --no-cache RUN apk add curl git
# build jid for later ARG BUILDARCH TARGETARCH
RUN go get -u github.com/simeji/jid/cmd/jid ENV BUILDARCH=$BUILDARCH \
CGO_ENABLED=0 \
GOARCH=$TARGETARCH \
TARGETARCH=$TARGETARCH
COPY helper-* /bin/
# main image with all the tools # https://github.com/docker/compose/releases
FROM alpine FROM builder AS compose
ARG TARGETPLATFORM ARG COMPOSE_VERSION=2.1.1
ARG BUILDPLATFORM RUN helper-curl bin docker-compose \
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log https://github.com/docker/compose/releases/download/v${COMPOSE_VERSION}/docker-compose-linux-@UARCH
ENV COMPOSE_VERSION=v2.0.0-beta.6 \ # https://github.com/google/go-containerregistry/tree/main/cmd/crane
# https://github.com/docker/compose-cli/releases FROM builder AS crane
HELM_VERSION=3.6.2 \ RUN go install github.com/google/go-containerregistry/cmd/crane@latest
# https://github.com/helm/helm/releases RUN cp $(find bin -name crane) /usr/local/bin
KUBECTL_VERSION=1.21.2 \
# https://dl.k8s.io/release/stable.txt
KUBECTX_VERSION=0.9.3 \
# https://github.com/ahmetb/kubectx/releases
STERN_VERSION=1.19.0 \
# https://github.com/stern/stern/releases
COMPLETIONS=/usr/share/bash-completion/completions
RUN apk add --no-cache bash bash-completion curl git jq libintl ncurses openssl tmux vim apache2-utils
# docker-compose # https://github.com/helm/helm/releases
RUN echo compose; case ${TARGETPLATFORM} in \ FROM builder AS helm
"linux/amd64") ARCH=amd64 ;; \ ARG HELM_VERSION=3.7.1
"linux/arm64") ARCH=arm64 ;; \ RUN helper-curl tar "--strip-components=1 linux-@GOARCH/helm" \
"linux/arm/v7") ARCH=armv7 ;; \ https://get.helm.sh/helm-v${HELM_VERSION}-linux-@GOARCH.tar.gz
esac \
&& mkdir -p /root/.docker/cli-plugins \
&& curl -sSLo /root/.docker/cli-plugins/docker-compose https://github.com/docker/compose-cli/releases/download/${COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /root/.docker/cli-plugins/docker-compose
# provide a note about the new compose cli if they try the old command # Use emulation instead of cross-compilation for that one.
COPY docker-compose /usr/local/bin/ # (The source is small enough, so I don't know if cross-compilation
# would be worth the effort.)
FROM alpine AS httping
RUN apk add build-base gettext git musl-libintl ncurses-dev
RUN git clone https://salsa.debian.org/debian/httping
WORKDIR httping
RUN sed -i s/60/0/ utils.c
RUN make install BINDIR=/usr/local/bin
# docker cli # https://github.com/simeji/jid/releases
COPY --from=docker /usr/local/bin/docker /usr/local/bin/docker FROM builder AS jid
ARG JID_VERSION=0.7.6
RUN go install github.com/simeji/jid/cmd/jid@v$JID_VERSION
RUN cp $(find bin -name jid) /usr/local/bin
# kubectl https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/ # https://github.com/derailed/k9s/releases
RUN echo kubectl; \ FROM builder AS k9s
case ${TARGETPLATFORM} in \ RUN helper-curl tar k9s \
"linux/amd64") ARCH=amd64 ;; \ https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_@WTFARCH.tar.gz
"linux/arm64") ARCH=arm64 ;; \
"linux/arm/v7") ARCH=arm ;; \
esac \
&& curl -sSLo /usr/local/bin/kubectl https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl \
&& chmod +x /usr/local/bin/kubectl
RUN kubectl completion bash > $COMPLETIONS/kubectl.bash
RUN kubectl config set-context kubernetes --namespace=default \
&& kubectl config use-context kubernetes
# stern https://github.com/stern/stern # https://github.com/kubernetes/kompose/releases
RUN echo stern; case ${TARGETPLATFORM} in \ FROM builder AS kompose
"linux/amd64") ARCH=amd64 ;; \ RUN helper-curl bin kompose \
"linux/arm64") ARCH=arm64 ;; \ https://github.com/kubernetes/kompose/releases/latest/download/kompose-linux-@GOARCH
"linux/arm/v7") ARCH=arm ;; \
esac \
&& curl -sSL https://github.com/stern/stern/releases/download/v${STERN_VERSION}/stern_${STERN_VERSION}_linux_${ARCH}.tar.gz \
| tar -zxo -C /usr/local/bin/ --strip-components=1 stern_${STERN_VERSION}_linux_${ARCH}/stern
RUN stern --completion bash > $COMPLETIONS/stern.bash
# helm https://github.com/helm/helm # https://github.com/kubernetes/kubernetes/releases
RUN echo helm; case ${TARGETPLATFORM} in \ FROM builder AS kubectl
"linux/amd64") ARCH=amd64 ;; \ ARG KUBECTL_VERSION=1.22.3
"linux/arm64") ARCH=arm64 ;; \ RUN helper-curl bin kubectl \
"linux/arm/v7") ARCH=arm ;; \ https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/@GOARCH/kubectl
esac \
&& curl -sSL https://get.helm.sh/helm-v${HELM_VERSION}-linux-${ARCH}.tar.gz \
| tar zxo -C /usr/local/bin --strip-components=1 linux-${ARCH}/helm
RUN helm completion bash > $COMPLETIONS/helm.bash
# httping https://github.com/BretFisher/httping-docker # https://github.com/stackrox/kube-linter/releases
COPY --from=bretfisher/httping /usr/local/bin/httping /usr/local/bin/httping FROM builder AS kube-linter
ARG KUBELINTER_VERSION=0.2.5
RUN go install golang.stackrox.io/kube-linter/cmd/kube-linter@$KUBELINTER_VERSION
RUN cp $(find bin -name kube-linter) /usr/local/bin
# kubectx and kubens https://github.com/ahmetb/kubectx # https://github.com/bitnami-labs/sealed-secrets/releases
RUN echo kubectx; case ${TARGETPLATFORM} in \ FROM builder AS kubeseal
"linux/amd64") ARCH=x86_64 ;; \ ARG KUBESEAL_VERSION=0.16.0
"linux/arm64") ARCH=arm64 ;; \ RUN helper-curl bin kubeseal \
"linux/arm/v7") ARCH=armhf ;; \ https://github.com/bitnami-labs/sealed-secrets/releases/download/v$KUBESEAL_VERSION/kubeseal-@KSARCH
esac \
&& curl -sSL https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubectx_v${KUBECTX_VERSION}_linux_${ARCH}.tar.gz \
| tar -zxo -C /usr/local/bin/ kubectx \
&& curl -sSL https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubens_v${KUBECTX_VERSION}_linux_${ARCH}.tar.gz \
| tar -zxo -C /usr/local/bin/ kubens \
&& curl -sSLo ${COMPLETIONS}/kubectx.bash https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubectx \
&& curl -sSLo ${COMPLETIONS}/kubens.bash https://github.com/ahmetb/kubectx/releases/download/v${KUBECTX_VERSION}/kubens
# kube-ps1 https://github.com/jonmosco/kube-ps1 # https://github.com/kubernetes-sigs/kustomize/releases
RUN echo kube-ps1; curl -sSLo /etc/profile.d/kube-ps1.sh https://raw.githubusercontent.com/jonmosco/kube-ps1/master/kube-ps1.sh FROM builder AS kustomize
ARG KUSTOMIZE_VERSION=4.4.1
RUN helper-curl tar kustomize \
https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v$KUSTOMIZE_VERSION/kustomize_v${KUSTOMIZE_VERSION}_linux_@GOARCH.tar.gz
# krew https://github.com/kubernetes-sigs/krew # https://ngrok.com/download
RUN echo krew; case ${TARGETPLATFORM} in \ FROM builder AS ngrok
"linux/amd64") ARCH=amd64 ;; \ RUN helper-curl tar ngrok \
"linux/arm64") ARCH=arm64 ;; \ https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-@GOARCH.tgz
"linux/arm/v7") ARCH=arm ;; \
esac \
&& mkdir /tmp/krew \
&& cd /tmp/krew \
&& curl -sSL https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-linux_${ARCH}.tar.gz \
| tar -zxf- \
&& ./krew-linux_${ARCH} install krew \
&& cd \
&& rm -rf /tmp/krew \
&& echo export 'PATH=$HOME/.krew/bin:$PATH' >> .bashrc
# TODO: add ship (no arm support). # https://github.com/derailed/popeye/releases
# It's superseded by Kots: FROM builder AS popeye
# TODO: add https://github.com/replicatedhq/kots RUN helper-curl tar popeye \
https://github.com/derailed/popeye/releases/latest/download/popeye_Linux_@WTFARCH.tar.gz
# k9s https://github.com/derailed/k9s # https://github.com/regclient/regclient/releases
RUN echo k9s; case ${TARGETPLATFORM} in \ FROM builder AS regctl
"linux/amd64") ARCH=x86_64 ;; \ ARG REGCLIENT_VERSION=0.3.9
"linux/arm64") ARCH=arm64 ;; \ RUN helper-curl bin regctl \
"linux/arm/v7") ARCH=arm ;; \ https://github.com/regclient/regclient/releases/download/v$REGCLIENT_VERSION/regctl-linux-@GOARCH
esac \
&& curl -sSL https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_${ARCH}.tar.gz \
| tar -zxo -C /usr/local/bin/ k9s
# popeye https://github.com/derailed/popeye # This tool is still used in the kustomize section, but we will probably
RUN echo popeye; case ${TARGETPLATFORM} in \ # deprecate it eventually as we only use a tiny feature that doesn't seem
"linux/amd64") ARCH=x86_64 ;; \ # to be available anymore in more recent versions (or requires some work
"linux/arm64") ARCH=arm64 ;; \ # to adapt). Also, it's not available on all platforms and doesn't compile.
"linux/arm/v7") ARCH=arm ;; \ FROM builder AS ship
esac \ ARG SHIP_VERSION=0.51.3
&& curl -sSL https://github.com/derailed/popeye/releases/latest/download/popeye_Linux_${ARCH}.tar.gz \ RUN helper-curl tar ship \
| tar -zxo -C /usr/local/bin popeye https://github.com/replicatedhq/ship/releases/download/v${SHIP_VERSION}/ship_${SHIP_VERSION}_linux_@GOARCH.tar.gz
# tilt https://github.com/tilt-dev/tilt # https://github.com/GoogleContainerTools/skaffold/releases/tag/v1.34.0
RUN echo tilt; case ${TARGETPLATFORM} in \ FROM builder AS skaffold
"linux/amd64") ARCH=x86_64 ;; \ RUN helper-curl bin skaffold \
"linux/arm64") ARCH=arm64_ALPHA ;; \ https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-@GOARCH
"linux/arm/v7") ARCH=arm_ALPHA ;; \
esac \
&& curl -sSL https://github.com/tilt-dev/tilt/releases/download/v0.19.0/tilt.0.19.0.linux.${ARCH}.tar.gz \
| tar -zxo -C /usr/local/bin tilt
# skaffold https://skaffold.dev # https://github.com/stern/stern/releases
# FIXME: wait for arm/v7 support and update FROM builder AS stern
# "linux/arm/v7") ARCH=arm ;; \ ARG STERN_VERSION=1.20.1
# https://github.com/GoogleContainerTools/skaffold/issues/5610 RUN helper-curl tar "--strip-components=1 stern_${STERN_VERSION}_linux_@GOARCH/stern" \
RUN echo skaffold; case ${TARGETPLATFORM} in \ https://github.com/stern/stern/releases/download/v${STERN_VERSION}/stern_${STERN_VERSION}_linux_@GOARCH.tar.gz
"linux/amd64") ARCH=amd64 ;; \
"linux/arm64") ARCH=arm64 ;; \
esac \
&& if test "${ARCH}" != "arm" ; \
then \
curl -sSLo /usr/local/bin/skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-${ARCH} \
&& chmod +x /usr/local/bin/skaffold ; \
fi
# kompose https://github.com/kubernetes/kompose # https://github.com/tilt-dev/tilt/releases/
RUN echo kompose; case ${TARGETPLATFORM} in \ FROM builder AS tilt
"linux/amd64") ARCH=amd64 ;; \ ARG TILT_VERSION=0.23.0
"linux/arm64") ARCH=arm64 ;; \ RUN helper-curl tar tilt \
"linux/arm/v7") ARCH=arm ;; \ https://github.com/tilt-dev/tilt/releases/download/v${TILT_VERSION}/tilt.${TILT_VERSION}.linux.@WTFARCH.tar.gz
esac \
&& curl -sSLo /usr/local/bin/kompose https://github.com/kubernetes/kompose/releases/latest/download/kompose-linux-${ARCH} \
&& chmod +x /usr/local/bin/kompose
#kubeseal https://github.com/bitnami-labs/sealed-secrets FROM alpine AS shpod
RUN echo kubeseal; case ${TARGETPLATFORM} in \ ENV COMPLETIONS=/usr/share/bash-completion/completions
"linux/amd64") ARCH=linux-amd64 ;; \ RUN apk add apache2-utils bash bash-completion curl docker-cli file git iputils jq libintl ncurses openssh openssl sudo tmux tree vim yq
"linux/arm64") ARCH=arm64 ;; \
"linux/arm/v7") ARCH=arm ;; \
esac \
&& curl -sSLo /usr/local/bin/kubeseal https://github.com/bitnami-labs/sealed-secrets/releases/download/latest/kubeseal-${ARCH} \
&& chmod +x /usr/local/bin/kubeseal
# jid https://github.com/simeji/jid COPY --from=compose /usr/local/bin/docker-compose /usr/local/bin
COPY --from=jid /go/bin/jid /usr/local/bin/jid COPY --from=crane /usr/local/bin/crane /usr/local/bin
COPY --from=helm /usr/local/bin/helm /usr/local/bin
COPY --from=httping /usr/local/bin/httping /usr/local/bin
COPY --from=jid /usr/local/bin/jid /usr/local/bin
COPY --from=k9s /usr/local/bin/k9s /usr/local/bin
COPY --from=kubectl /usr/local/bin/kubectl /usr/local/bin
COPY --from=kube-linter /usr/local/bin/kube-linter /usr/local/bin
COPY --from=kubeseal /usr/local/bin/kubeseal /usr/local/bin
COPY --from=kustomize /usr/local/bin/kustomize /usr/local/bin
COPY --from=ngrok /usr/local/bin/ngrok /usr/local/bin
COPY --from=popeye /usr/local/bin/popeye /usr/local/bin
COPY --from=regctl /usr/local/bin/regctl /usr/local/bin
COPY --from=ship /usr/local/bin/ship /usr/local/bin
COPY --from=skaffold /usr/local/bin/skaffold /usr/local/bin
COPY --from=stern /usr/local/bin/stern /usr/local/bin
COPY --from=tilt /usr/local/bin/tilt /usr/local/bin
# final shell environment prep RUN set -e ; for BIN in \
WORKDIR /root crane \
RUN echo trap exit TERM > /etc/profile.d/trapterm.sh helm \
RUN sed -i "s/export PS1=/#export PS1=/" /etc/profile kubectl \
RUN sed -i s,/bin/ash,/bin/bash, /etc/passwd kube-linter \
ENV HOSTIP="0.0.0.0" \ kustomize \
TERM="xterm-256color" \ regctl \
KUBE_PS1_PREFIX="" \ skaffold \
KUBE_PS1_SUFFIX="" \ tilt \
KUBE_PS1_SYMBOL_ENABLE="false" \ ; do echo $BIN ; $BIN completion bash > $COMPLETIONS/$BIN.bash ; done ;\
KUBE_PS1_CTX_COLOR="green" \ yq shell-completion bash > $COMPLETIONS/yq.bash
KUBE_PS1_NS_COLOR="green"
ENV PS1="\e[1m\e[31m[\$HOSTIP] \e[32m(\$(kube_ps1)) \e[34m\u@\h\e[35m \w\e[0m\n$ " RUN cd /tmp \
CMD ["bash", "-l"] && git clone https://github.com/ahmetb/kubectx \
&& cd kubectx \
&& mv kubectx /usr/local/bin/kctx \
&& mv kubens /usr/local/bin/kns \
&& mv completion/kubectx.bash $COMPLETIONS/kctx.bash \
&& mv completion/kubens.bash $COMPLETIONS/kns.bash \
&& cd .. \
&& rm -rf kubectx
RUN cd /tmp \
&& git clone https://github.com/jonmosco/kube-ps1 \
&& cp kube-ps1/kube-ps1.sh /etc/profile.d/ \
&& rm -rf kube-ps1
# Create user and finalize setup.
RUN echo k8s:x:1000: >> /etc/group \
&& echo k8s:x:1000:1000::/home/k8s:/bin/bash >> /etc/passwd \
&& echo "k8s ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/k8s \
&& mkdir /home/k8s \
&& chown -R k8s:k8s /home/k8s/ \
&& sed -i 's/#MaxAuthTries 6/MaxAuthTries 42/' /etc/ssh/sshd_config
ARG TARGETARCH
RUN mkdir /tmp/krew \
&& cd /tmp/krew \
&& curl -fsSL https://github.com/kubernetes-sigs/krew/releases/latest/download/krew-linux_$TARGETARCH.tar.gz | tar -zxf- \
&& sudo -u k8s -H ./krew-linux_$TARGETARCH install krew \
&& cd \
&& rm -rf /tmp/krew
COPY --chown=1000:1000 bash_profile /home/k8s/.bash_profile
COPY --chown=1000:1000 vimrc /home/k8s/.vimrc
COPY motd /etc/motd
COPY setup-tailhist.sh /usr/local/bin
# Generate a list of all installed versions.
RUN ( \
ab -V | head -n1 ;\
bash --version | head -n1 ;\
curl --version | head -n1 ;\
docker version --format="Docker {{.Client.Version}}" ;\
git --version ;\
jq --version ;\
ssh -V ;\
tmux -V ;\
yq --version ;\
docker-compose version ;\
echo "crane $(crane version)" ;\
echo "Helm $(helm version --short)" ;\
httping --version ;\
jid --version ;\
echo "k9s $(k9s version | grep Version)" ;\
echo "kubectl $(kubectl version --short --client)" ;\
echo "kube-linter $(kube-linter version)" ;\
kubeseal --version ;\
kustomize version --short ;\
ngrok version ;\
echo "popeye $(popeye version | grep Version)" ;\
echo "regctl $(regctl version --format={{.VCSTag}})" ;\
echo "ship $(ship version | jq .version)" ;\
echo "skaffold $(skaffold version)" ;\
echo "stern $(stern --version | grep ^version)" ;\
echo "tilt $(tilt version)" ;\
) > versions.txt
# If there is a tty, give us a shell.
# (This happens e.g. when we do "docker run -ti bretfisher/shpod".)
# Otherwise, start an SSH server.
# (This happens e.g. when we use that image in a Pod in a Deployment.)
CMD \
if tty >/dev/null; then \
exec login -f k8s && \
: ; \
else \
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && \
echo k8s:${PASSWORD-k8s} | chpasswd && \
exec /usr/sbin/sshd -D -e && \
: ; \
fi
EXPOSE 22/tcp

125
README.md
View File

@@ -5,29 +5,50 @@
**TL,DR:** `curl https://k8smastery.com/shpod.sh | sh` **TL,DR:** `curl https://k8smastery.com/shpod.sh | sh`
If you are looking for an image that works on the ARM architecture
(like the Raspberry Pi or the Apple M1), have a look at
[BretFisher/shpod](https://github.com/BretFisher/shpod) instead.
Bret's fork is also a state-of-the-art example of a multi-arch
Dockerfile!
## What's this? ## What's this?
`shpod` is a container image based on the Alpine distribution `shpod` is a container image based on the Alpine distribution
and embarking a bunch of tools useful when working with Kubernetes: and embarking a bunch of tools useful when working with containers,
Docker, and Kubernetes.
- compose It includes:
- helm
- ab (ApacheBench)
- bash
- crane
- curl
- Docker CLI
- Docker Compose
- git
- Helm
- jid - jid
- jq - jq
- krew
- kubectl - kubectl
- kubectx + kubens - kubectx + kubens
- kube-linter
- kube-ps1 - kube-ps1
- kubeseal - kubeseal
- k9s - kustomize
- ngrok
- popeye
- regctl
- ship - ship
- skaffold - skaffold
- skopeo
- SSH
- stern - stern
- tilt - tilt
- tmux
- yq
It also includes tmux, a custom prompt, and completion for It also includes completion for most of these tools.
all of the above.
Its goal is to provide a normalized environment, to go Its goal is to provide a normalized environment, to go
with the training materials at [kubernetesmastery.com](https://kubernetesmastery.com), with the training materials at [kubernetesmastery.com](https://kubernetesmastery.com),
@@ -37,6 +58,68 @@ of your exact Kubernetes setup.
To use it, you need a Kubernetes cluster. You can use Minikube, To use it, you need a Kubernetes cluster. You can use Minikube,
microk8s, Docker Desktop, AKS, EKS, GKE, anything you like, really. microk8s, Docker Desktop, AKS, EKS, GKE, anything you like, really.
If it runs with a pseudo-terminal, it will spawn a shell, and you
can attach to that shell. If it runs without a pseudo-terminal,
it will start an SSH server, and you can connect to that SSH
server to obtain the shell.
## Using with a pseudo-terminal
Run it in a Pod and attach directly to it:
```bash
kubectl run shpod --restart=Never --rm -it --image=bretfisher/shpod
```
This should give you a shell in a pod, with all the tools installed.
Most Kubernetes commands won't work (you will get permission errors)
until you create an appropriate RoleBinding or ClusterRoleBinding
(see below for details).
## Using without a pseudo-terminal
Run as a Pod (or Deployment), then expose (or port-forward) to port
22 in that Pod, and connect with an SSH client:
```bash
kubectl run shpod --image=bretfisher/shpod
kubectl wait pod shpod --for=condition=ready
kubectl port-forward pod/shpod 2222:22
ssh -l k8s -p 2222 localhost # the default password is "k8s"
```
Note: you can change the password by setting the `PASSWORD`
environment variable.
## Granting permissions
By default, shpod uses the ServiceAccount of the Pod that it's
running in; and by default (on most clusters) that ServiceAccount
won't have much permissions, meaning that you will get errors like
the following one:
```console
$ kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:default" cannot list resource "pods" in API group "" in the namespace "default"
```
If you want to use Kubernetes commands within shpod, you need
to give permissions to that ServiceAccount.
Assuming that you are running shpod in the `default` namespace
and with the `default` ServiceAccount, you can run the following
command to give `cluster-admin` privileges (=all privileges) to
the commands running in shpod:
```bash
kubectl create clusterrolebinding shpod \
--clusterrole=shpod \
--serviceaccount=default:default
```
You can also use the one-liner below.
## One-liner usage ## One-liner usage
@@ -47,6 +130,15 @@ The [shpod.sh](shpod.sh) script will:
- attach to that pod, - attach to that pod,
- delete resources created by the manifest when you exit the pod. - delete resources created by the manifest when you exit the pod.
The manifest will:
- create the `shpod` Namespace,
- create the `shpod` ServiceAccount in that Namespace,
- create the `shpod` ClusterRoleBinding giving `cluster-admin`
privileges to that ServiceAccount,
- create a Pod named `shpod`, using that ServiceAccount, with
a terminal (so that you can attach to that Pod and get a shell).
To execute it: To execute it:
```bash ```bash
@@ -71,7 +163,6 @@ step by step, check the next section.
3. Enjoy! 3. Enjoy!
## Clean up ## Clean up
If you are using the shell script above, when you exit shpod, If you are using the shell script above, when you exit shpod,
@@ -85,7 +176,6 @@ and the ClusterRoleBinding with the same name:
kubectl delete clusterrolebinding,ns shpod kubectl delete clusterrolebinding,ns shpod
``` ```
## Internal details ## Internal details
The YAML file is a Kubernetes manifest for a Pod, a ServiceAccount, The YAML file is a Kubernetes manifest for a Pod, a ServiceAccount,
@@ -94,7 +184,6 @@ a ClusterRoleBinding, and a Namespace to hold the Pod and ServiceAccount.
The Pod uses image [bretfisher/shpod](https://hub.docker.com/r/bretfisher/shpod) The Pod uses image [bretfisher/shpod](https://hub.docker.com/r/bretfisher/shpod)
on the Docker Hub, built from this repository [github.com/bretfisher/shpod](https://github.com/bretfisher/shpod). on the Docker Hub, built from this repository [github.com/bretfisher/shpod](https://github.com/bretfisher/shpod).
## Opening multiple sessions ## Opening multiple sessions
Shpod tries to detect if it is already running; and if it's the case, Shpod tries to detect if it is already running; and if it's the case,
@@ -103,3 +192,19 @@ if the first shpod process exits, Kubernetes will terminate all the
other processes. other processes.
## Thanks to @jpetazzo for this great open source ## Thanks to @jpetazzo for this great open source
## Special handling of kubeconfig
If you have a ConfigMap named `kubeconfig` in the Namespace
where shpod is running, it will extract the first file from
that ConfigMap and use it to populate `~/.kube/config`.
This lets you inject a custom kubeconfig file into shpod.
## Support for other architectures
As of November 2021, the Dockerfile in this repository should be able
to build images for other architectures. However, when trying to install
a compiled binary that is not available for another architecture, a dummy
placeholder will be installed instead.

64
bash_profile Normal file
View File

@@ -0,0 +1,64 @@
# If we don't have a kubeconfig file, let's create one.
# (This is necessary for kube_ps1 to operate correctly.)
if ! [ -f ~/.kube/config ]; then
# If there is a ConfigMap named 'kubeconfig',
# extract the kubeconfig file from there.
# We need to access the Kubernetes API, so we'll do it
# using the well-known endpoint.
(
export KUBERNETES_SERVICE_HOST=kubernetes.default.svc
export KUBERNETES_SERVICE_PORT=443
if kubectl get configmap kubeconfig >&/dev/null; then
echo "✏️ Downloading ConfigMap kubeconfig to .kube/config."
kubectl get configmap kubeconfig -o json |
jq -r '.data | to_entries | .[0].value' > ~/.kube/config
else
SADIR=/var/run/secrets/kubernetes.io/serviceaccount
# If we have a ServiceAccount token, use it.
if [ -r $SADIR/token ]; then
echo "✏️ Generating .kube/config using ServiceAccount token."
kubectl config set-cluster shpod \
--server=https://kubernetes.default.svc \
--certificate-authority=/$SADIR/ca.crt
kubectl config set-credentials shpod \
--token=$(cat $SADIR/token )
kubectl config set-context shpod \
--cluster=shpod \
--user=shpod
kubectl config use-context shpod
fi
fi
)
fi
# Note that we could also just set the following variables:
#export KUBERNETES_SERVICE_HOST=kubernetes.default.svc
#export KUBERNETES_SERVICE_PORT=443
# ...But for some reason, that doesn't work with impersonation.
# (i.e. using "kubectl get pods --as=someone.else")
if [ -f /etc/HOSTIP ]; then
HOSTIP=$(cat /etc/HOSTIP)
else
HOSTIP="0.0.0.0"
fi
KUBE_PS1_PREFIX=""
KUBE_PS1_SUFFIX=""
KUBE_PS1_SYMBOL_ENABLE="false"
KUBE_PS1_CTX_COLOR="green"
KUBE_PS1_NS_COLOR="green"
PS1="\e[1m\e[31m[\$HOSTIP] \e[0m(\$(kube_ps1)) \e[34m\u@\h\e[35m \w\e[0m\n$ "
export EDITOR=vim
export PATH="$HOME/.krew/bin:$PATH"
alias k=kubectl
complete -F __start_kubectl k
. /usr/share/bash-completion/completions/kubectl.bash
export HISTSIZE=9999
export HISTFILESIZE=9999
shopt -s histappend
trap 'history -a' DEBUG
export HISTFILE=~/.history
trap exit TERM

71
helper-curl Executable file
View File

@@ -0,0 +1,71 @@
#!/bin/sh
set -e
TYPE=$1
BIN_OR_ARGS=$2
URL=$3
case $TARGETARCH in
amd64)
GOARCH=amd64
KSARCH=linux-amd64
UARCH=x86_64
WTFARCH=x86_64
;;
arm64)
GOARCH=arm64
KSARCH=arm64
UARCH=aarch64
WTFARCH=arm64
;;
arm)
GOARCH=arm
KSARCH=arm
UARCH=armv7
WTFARCH=arm
;;
*)
echo "Unsupported architecture: $TARGETARCH."
GOARCH=$TARGETARCH
KSARCH=$TARGETARCH
UARCH=$TARGETARCH
WTFARCH=$TARGETARCH
;;
esac
mangle() {
echo $1 | sed \
-e s/@GOARCH/$GOARCH/g \
-e s/@KSARCH/$KSARCH/g \
-e s/@UARCH/$UARCH/g \
-e s/@WTFARCH/$WTFARCH/g \
#
}
URL=$(mangle $URL)
BIN_OR_ARGS=$(mangle "$BIN_OR_ARGS")
if ! curl -fsSLI $URL >/dev/null; then
echo "URL not found: $URL"
BIN=${BIN_OR_ARGS##*/}
echo "Installing placeholder: $BIN"
cp /bin/helper-unsupported /usr/local/bin/$BIN
exit 0
fi
case "$TYPE" in
bin)
BIN=$BIN_OR_ARGS
curl -fsSL $URL > /usr/local/bin/$BIN
chmod +x /usr/local/bin/$BIN
;;
tar)
ARGS=$BIN_OR_ARGS
curl -fsSL $URL | tar -zxvf- -C /usr/local/bin $ARGS
;;
*)
echo "Unrecognized download type: $TYPE"
exit 1
;;
esac

3
helper-go Normal file
View File

@@ -0,0 +1,3 @@
CGO_ENABLED=0 \

2
helper-unsupported Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
echo "# $0 is not supported on this platform ($(uname -m))."

6
motd Normal file
View File

@@ -0,0 +1,6 @@
🐚 Welcome to shpod - SHell in a POD.
🔎 Check "/versions.txt" to see the list of included tools.
🔗 See https://github.com/bretfisher/shpod for more information.
📦️ You can install extra packages with 'sudo apk add PKGNAME'.

21
setup-tailhist.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
set -ex
mkdir /tmp/tailhist
cd /tmp/tailhist
WEBSOCKETD_VERSION=0.4.1
wget https://github.com/joewalnes/websocketd/releases/download/v$WEBSOCKETD_VERSION/websocketd-$WEBSOCKETD_VERSION-linux_amd64.zip
unzip websocketd-$WEBSOCKETD_VERSION-linux_amd64.zip
curl https://raw.githubusercontent.com/jpetazzo/container.training/main/prepare-vms/lib/tailhist.html > index.html
kubectl patch service shpod --namespace shpod -p "
spec:
ports:
- name: tailhist
port: 1088
targetPort: 1088
nodePort: 30088
protocol: TCP
"
./websocketd --port=1088 --staticdir=. sh -c "
tail -n +1 -f $HOME/.history ||
echo 'Could not read history file. Perhaps you need to \"chmod +r .history\"?'
"

7
vimrc Normal file
View File

@@ -0,0 +1,7 @@
syntax on
set autoindent
set expandtab
set number
set shiftwidth=2
set softtabstop=2
set nowrap