diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..983d48f --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,5 @@ +{ + "tasks": { + "build": "docker build -t k8s-sherlock:latest ." + } +} \ No newline at end of file diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml new file mode 100644 index 0000000..41ad5a4 --- /dev/null +++ b/.github/workflows/build-and-publish.yml @@ -0,0 +1,87 @@ +name: Build and Publish Docker Image + +on: + push: + branches: [ main ] + tags: [ 'v*' ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + arunsanna/k8s-sherlock + tags: | + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,format=short + + # Build the image locally first (for scanning) + - name: Build Docker image locally + uses: docker/build-push-action@v5 + with: + context: . + load: true # Load the image into Docker's local image store + tags: k8s-sherlock:local + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + # Run Trivy on the local image + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + image-ref: 'k8s-sherlock:local' + format: 'table' + exit-code: '0' # Don't fail the build, just report + ignore-unfixed: true + vuln-type: 'os,library' + severity: 'CRITICAL,HIGH' + + # Now login and push to Docker Hub + - name: Login to Docker Hub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + # Build and push to Docker Hub + - name: Build and push Docker image + if: github.event_name != 'pull_request' + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache \ No newline at end of file diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index f3b6dc5..0000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: build-images - -on: - push: - branches: - - 'main' - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - - name: Checkout - uses: actions/checkout@v2 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - push: true - tags: arunsanna/k8s-sherlock:latest \ No newline at end of file diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD new file mode 100644 index 0000000..b98b849 --- /dev/null +++ b/CONTRIBUTING.MD @@ -0,0 +1,93 @@ +# Contributing to K8s-Sherlock + +Thank you for considering contributing to K8s-Sherlock! This project thrives due to community involvement, and we appreciate your support. Below are guidelines to help you contribute effectively. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [How to Contribute](#how-to-contribute) +- [Report Bugs](#report-bugs) +- [Request Features](#request-features) +- [Review Pull Requests](#review-pull-requests) +- [Code Standards](#code-standards) +- [License](#license) + +## Code of Conduct + +By participating in this project, you are expected to uphold our [Code of Conduct](CODE_OF_CONDUCT.md). Please read it before contributing. + +## How to Contribute + +### 1. Fork the Repository + +Fork the [K8s-Sherlock GitHub repository](https://github.com/VivSoftOrg/k8s-sherlock/tree/develop). + +### 2. Clone Your Fork + +```bash +git clone https://github.com/yourusername/k8s-sherlock.git +cd k8s-sherlock +``` + +### 3. Set Up Remote Upstream + +```bash +git remote add upstream https://github.com/VivSoftOrg/k8s-sherlock.git +``` + +### 4. Create a New Branch + +```bash +git checkout -b feature/your-feature-name +``` + +### 5. Make Changes + +Make your changes, keeping in mind the project's code standards. + +### 6. Commit Your Changes + +```bash +git commit -m "Implement XYZ feature" +``` + +### 7. Update Your Branch + +```bash +git fetch upstream +git rebase upstream/develop +``` + +### 8. Push Changes to GitHub + +```bash +git push origin feature/your-feature-name +``` + +### 9. Create a Pull Request + +Navigate to the GitHub page of your fork and click on "New Pull Request." + +## Report Bugs + +If you encounter a bug, please open a GitHub issue. Include as many details as possible, such as how to reproduce the bug and what you expected to happen. + +## Request Features + +Feature requests are welcome. Open an issue on GitHub to suggest a new feature. Explain why it would be beneficial and how it should function. + +## Review Pull Requests + +Reviewing pull requests is another way to contribute. Check the open pull requests and provide feedback. + +## Code Standards + +- Write clean and understandable code. +- Comment your code where necessary. +- Update documentation as needed. + +## License + +By contributing, you agree that your contributions will be licensed under the project's MIT License. + +Thank you for contributing to K8s-Sherlock! diff --git a/Dockerfile b/Dockerfile index 1aed642..7cdf4e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,45 +1,112 @@ -# Use the official Ubuntu base image -FROM ubuntu:latest +FROM debian:bullseye-slim -# Set up environment variables +# Set environment variables ENV DEBIAN_FRONTEND=noninteractive -# Update package list and install common networking tools -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ +# Install basic tools +RUN apt-get update && apt-get install -y --no-install-recommends \ apt-transport-https \ ca-certificates \ - gnupg-agent \ - software-properties-common \ - iproute2 \ - iputils-ping \ - traceroute \ - netcat \ - dnsutils \ - telnet \ curl \ + gnupg \ + lsb-release \ wget \ + git \ + vim \ + procps \ + net-tools \ + dnsutils \ + iputils-ping \ + netcat \ + tcpdump \ + iproute2 \ + jq \ + python3 \ + python3-pip \ + unzip \ + socat \ + fzf \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* -# Add Docker’s official GPG key -RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - +# Install kubectl +RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \ + && chmod +x kubectl \ + && mv kubectl /usr/local/bin/ -# Add Docker repository -RUN add-apt-repository \ - "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) \ - stable" +# Install Helm +RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash -# Install Docker CLI -RUN apt-get update && apt-get install -y docker-ce-cli +# Install k9s +RUN curl -sS https://webinstall.dev/k9s | bash -# Install Python, pip and AWS CLI -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - python3 \ - python3-pip \ - && rm -rf /var/lib/apt/lists/* && \ - pip3 install --upgrade awscli +# Install kubectx and kubens +RUN git clone https://github.com/ahmetb/kubectx /opt/kubectx \ + && ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx \ + && ln -s /opt/kubectx/kubens /usr/local/bin/kubens + +# Install krew +RUN set -ex; \ + cd "$(mktemp -d)" && \ + OS="$(uname | tr '[:upper:]' '[:lower:]')" && \ + ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" && \ + KREW="krew-${OS}_${ARCH}" && \ + curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" && \ + tar zxvf "${KREW}.tar.gz" && \ + ./"${KREW}" install krew && \ + echo 'export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"' >> /etc/profile.d/krew.sh && \ + echo 'export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"' >> /root/.bashrc + +# Install stern +RUN curl -L -o stern.tar.gz https://github.com/stern/stern/releases/latest/download/stern_$(curl -s https://api.github.com/repos/stern/stern/releases/latest | grep tag_name | cut -d '"' -f 4 | cut -c 2-)_linux_amd64.tar.gz \ + && tar -xzf stern.tar.gz \ + && chmod +x stern \ + && mv stern /usr/local/bin/ \ + && rm stern.tar.gz LICENSE + +# Install kustomize +RUN curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash \ + && mv kustomize /usr/local/bin/ + +# Install yq +RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 \ + && chmod +x /usr/local/bin/yq + +# Install trivy +RUN wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor -o /usr/share/keyrings/trivy-archive-keyring.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/trivy-archive-keyring.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/trivy.list \ + && apt-get update \ + && apt-get install -y trivy \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install kubeconform +RUN KUBECONFORM_VERSION=$(curl -s https://api.github.com/repos/yannh/kubeconform/releases/latest | grep tag_name | cut -d '"' -f 4) \ + && wget -q "https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz" \ + && tar xzf kubeconform-linux-amd64.tar.gz \ + && mv kubeconform /usr/local/bin/ \ + && rm kubeconform-linux-amd64.tar.gz + +# Install kubectl plugins via krew +RUN /bin/bash -c "export PATH=\"/root/.krew/bin:\$PATH\" && \ + kubectl krew install ctx ns neat" + +# Install dive (container image explorer) directly instead of as krew plugin +RUN DIVE_VERSION=$(curl -s https://api.github.com/repos/wagoodman/dive/releases/latest | grep tag_name | cut -d '"' -f 4) \ + && ARCH=$(dpkg --print-architecture) \ + && curl -OL https://github.com/wagoodman/dive/releases/download/${DIVE_VERSION}/dive_${DIVE_VERSION#v}_linux_${ARCH}.deb \ + && dpkg -i dive_${DIVE_VERSION#v}_linux_${ARCH}.deb \ + && rm dive_${DIVE_VERSION#v}_linux_${ARCH}.deb + +# Make krew available in PATH by default +ENV PATH="/root/.krew/bin:${PATH}" + +# Install telepresence for local development +RUN curl -fL https://app.getambassador.io/download/tel2/linux/amd64/latest/telepresence -o /usr/local/bin/telepresence \ + && chmod a+x /usr/local/bin/telepresence + +# Create working directory +WORKDIR /app # Set entrypoint to bash -ENTRYPOINT ["/bin/bash"] +ENTRYPOINT ["/bin/bash"] \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..9af34c9 --- /dev/null +++ b/Readme.md @@ -0,0 +1,91 @@ +# K8s-Sherlock: Kubernetes Debugging Toolkit + +A comprehensive debugging and troubleshooting toolkit for Kubernetes environments, packaged in a single container based on Debian slim. + +## Included Tools + +- **Kubernetes Tools**: kubectl, helm, kustomize, kubectx/kubens, stern, krew +- **Cluster Exploration**: k9s, kubectl-neat, dive +- **Security**: trivy, kubeconform +- **Development**: telepresence +- **Networking**: iproute2, iputils-ping, netcat, tcpdump, dnsutils, socat +- **JSON/YAML Processing**: jq, yq +- **Utilities**: curl, wget, git, vim, fzf, and more + +## Usage + +### Run as a container in your cluster + +```bash +kubectl run sherlock --rm -it --image=ghcr.io/arunsanna/k8s-sherlock --restart=Never -- bash +``` + +--- + +CI/CD Pipeline +-------- + +The project includes GitHub Actions workflows for: +* Automated builds on pushes to main branch and tags +* Container image publishing to GitHub Container Registry +* Security scanning with Trivy to detect vulnerabilities +* Layer caching for faster builds + +Features +-------- + +* **Networking Tools**: Comes with `iproute2`, `iputils-ping`, `netcat`, `dnsutils`, `tcpdump`, and `socat` +* **HTTP Tools**: `curl` and `wget` pre-installed for HTTP requests +* **Kubernetes Development**: Full suite of K8s tools including kubectl plugins via krew +* **Interactive Tools**: Terminal-based UIs like k9s and fzf for better productivity + +--- + +Quick Start +----------- + +### Prerequisites + +* A Kubernetes cluster up and running +* kubectl installed and configured + +### Deploy K8s-Sherlock Pod + +```bash +kubectl apply -f pod/sherlock.yml --namespace= +``` + +### Run Standalone + +You can also pull and run the container directly with Docker: + +```bash +docker run -it --rm ghcr.io/arunsanna/k8s-sherlock +``` + +--- + +Usage +----- + +Once the K8s-Sherlock pod is up and running, you can `exec` into it to use the tools. + +bash + +```bash +kubectl exec -it -- /bin/bash +``` + +--- + +Contributing +------------ + +We love contributions! Please read the [Contributing Guidelines](CONTRIBUTING.MD) for more information on how to get involved. + +--- + +License +------- + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. diff --git a/pod-sa/debugger.yml b/pod-sa/debugger.yml deleted file mode 100644 index fa37cbd..0000000 --- a/pod-sa/debugger.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -apiVersion: v1 -kind: Pod -metadata: - name: a-debugger-pod -spec: - serviceAccountName: my-service-account - containers: - - name: a-debugger-container - image: a-debugger:latest - command: ["/bin/sh"] - args: ["-c", "while true; do sleep 60; done"] - restartPolicy: Always ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: my-service-account - annotations: - eks.amazonaws.com/role-arn: - diff --git a/pod/debugger.yml b/pod/debugger.yml deleted file mode 100644 index fa37cbd..0000000 --- a/pod/debugger.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -apiVersion: v1 -kind: Pod -metadata: - name: a-debugger-pod -spec: - serviceAccountName: my-service-account - containers: - - name: a-debugger-container - image: a-debugger:latest - command: ["/bin/sh"] - args: ["-c", "while true; do sleep 60; done"] - restartPolicy: Always ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: my-service-account - annotations: - eks.amazonaws.com/role-arn: - diff --git a/pod/sherlock.yml b/pod/sherlock.yml new file mode 100644 index 0000000..3445216 --- /dev/null +++ b/pod/sherlock.yml @@ -0,0 +1,55 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sherlock-sa +--- +apiVersion: v1 +kind: Pod +metadata: + name: sherlock +spec: + containers: + - name: sherlock + image: arunsanna/k8s-sherlock:latest + command: ["/bin/sh"] + args: ["-c", "while true; do sleep 300; done"] + resources: + limits: + cpu: "1" + memory: "1Gi" + requests: + cpu: "0.5" + memory: "512Mi" + livenessProbe: + exec: + command: + - "/bin/bash" + - "-c" + - "echo Hello, Sherlock!" + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + exec: + command: + - "/bin/bash" + - "-c" + - "echo Ready!" + initialDelaySeconds: 5 + periodSeconds: 10 + nodeSelector: {} + tolerations: + + - key: CriticalAddonsOnly + operator: Exists + effect: NoSchedule + - key: node.kubernetes.io/not-ready + operator: Exists + effect: NoExecute + tolerationSeconds: 300 + - key: node.kubernetes.io/unreachable + operator: Exists + effect: NoExecute + tolerationSeconds: 300 + restartPolicy: Always + diff --git a/tests/test.sh b/tests/test.sh new file mode 100644 index 0000000..fff71ed --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -e + +# Build the Docker image +echo "Building Docker image..." +docker build -t test-image . + +# Run the container +echo "Running Docker container..." +container_id=$(docker run -d test-image:latest) + +# Helper function to run commands inside the container +run_command() { + docker exec $container_id "$@" +} + +# Test kubectl installation +echo "Testing kubectl installation..." +run_command kubectl version --client + +# Test helm installation +echo "Testing helm installation..." +run_command helm version + +# All tests passed +echo "All tests passed successfully." + +# Cleanup +docker stop $container_id +docker rmi test-image