フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

【新規ツール探し】kubectl debug で使えるコンテナイメージ「koolkits」

  • 記事作成日:2022/12/08

情報

名前 URL
Github https://github.com/lightrun-platform/koolkits
公式サイト
デモサイト
開発母体 Lightrun
version -
言語 Dockerfile
価格 無料
ライセンス Apache-2.0 license

何ができるもの?

Kubernetes(k8s) で利用できるデバッグ用のコンテナイメージ。

kubectl debug によって ephemeral container として起動し、トラブルシュートしたいコンテナと同じプロセス名前空間にアクセスできるようになる。

利用シーン

  • k8s 上のコンテナに対するデバッグ

登場背景

by DeepL

Kubernetesのベストプラクティスとして、「小さなコンテナイメージを構築すべき」というものがよく知られています。これは、いくつかの異なる理由から理にかなっています。

  1. イメージのビルドにかかるリソースが少なくなる(CI時間など)
  2. イメージのプルにはより多くの時間がかかる(誰がイングレスのためにお金を払いたいだろうか?)
  3. ログを取らないことでさえ安全でなくなってきている現在、セキュリティの脆弱性にさらされる領域が少なくなる。

また、多くのツールが存在し、あまり重い荷物を持たずにそこに到達するのを助けてくれます。

  • Alpine Linuxのベースイメージは超小型です。
  • DistroLess Dockerイメージはさらに一歩進んで、ランタイム以外のすべてを削除します。
  • Dockerの多段階ビルドは、薄い最終製品イメージの作成を支援します。

問題は、コンテナ内で何が起こっているかをデバッグしようとするときから始まります。小さな本番イメージを使用することで、アプリケーションの問題に頭を悩ませる際に貴重なツールを大量に見送ることになります。

KoolKit を使用することで、高品質のツールに妥協することなく、小さな製品イメージの利点を得ることができます。各 KoolKit には、Linux ベースのシステム用の汎用ツールに加えて、それが表す特定のランタイム用に厳選されたツールが含まれています。

所感

  • kubectl debug をする際に使えるコンテナイメージの配布
  • 対応が python / node / go / jvm
  • パッと使うには便利だと思うし、デバッグツールなのでそこまで細かいとこは気にならない

言語ごとのイメージに入ってるツール一覧はここ。

使い方

今回使ったコード

準備

docker 公式の go のアプリ)をお借りします。

なお、今回使ったイメージをここにアップしているので docker push lirlia/sample-go-http-server:latest でも使用可能です。

package main

import (
    "net/http"
    "os"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {

    e := echo.New()

    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    e.GET("/", func(c echo.Context) error {
        return c.HTML(http.StatusOK, "Hello, Docker! <3")
    })

    e.GET("/ping", func(c echo.Context) error {
        return c.JSON(http.StatusOK, struct{ Status string }{Status: "OK"})
    })

    httpPort := os.Getenv("HTTP_PORT")
    if httpPort == "" {
        httpPort = "8080"
    }

    e.Logger.Fatal(e.Start(":" + httpPort))
}

ビルドして

❯ ko build --local
2022/12/08 09:24:17 Using base distroless.dev/static:latest@sha256:f89f7e7b28a8a4b8cf467e9712d9675b54ae9571329f63db4e96f785b666914a for github.com/test
2022/12/08 09:24:17 Building github.com/test for linux/amd64
2022/12/08 09:24:24 Loading ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434:507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da
2022/12/08 09:24:25 Loaded ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434:507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da
2022/12/08 09:24:25 Adding tag latest
2022/12/08 09:24:25 Added tag latest
ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434:507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da
ko build --local  16.57s user 3.60s system 163% cpu 12.309 total
❯ 
❯ docker images ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434:507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da
REPOSITORY                                       TAG                                                                IMAGE ID       CREATED          SIZE
ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434   507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da   aa1e8bae6a82   15 minutes ago   9MB
❯ kind create cluster --name 1 

# イメージの転送
❯ kind --name 1 load docker-image ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434:507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da
Image: "" with ID "sha256:aa1e8bae6a82335ddfef738582fe2922dbd7e72772e7dd9f7511d3238e0b9cb0" not yet present on node "1-control-plane", loading...

❯ kubectl create deployment go-app --image=ko.local/test-b1e961c37ef3cc8dcc1a152c78ed9434:507acb9e5e2026fe7178c0f1f4f00b90dbad1eacfce4c620bb2b16fd93b7e0da
deployment.apps/go-app created

❯ kubectl get deployments.apps go-app
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
go-app   1/1     1            1           15s

❯ kubectl port-forward go-app-67bcfbcc98-xltgn 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Handling connection for 8080

別ターミナルで接続できることを確認します

❯ curl localhost:8080
Hello, Docker! <3   

デバッグしてみる

distroless イメージなのでシェルもなく go-app には入れない。

❯ kubectl exec -it go-app-67bcfbcc98-xltgn -- /bin/sh
error: Internal error occurred: error executing command in container: failed to exec in container: failed to start exec "fb95733d9c3b3fa620eff67f6ab75e9f66550803192d7c80bcc3b5925b8f1cd8": OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknown

Pod名、コンテナ名をつけてログインします。(image-pull-policy=Never になってるといつまでもイメージダウンロードされないので注意)

❯ kubectl debug -it go-app-67bcfbcc98-xltgn --image=lightruncom/koolkits:golang --target=test-b1e961c37ef3cc8dcc1a152c78ed9434
Targeting container "test-b1e961c37ef3cc8dcc1a152c78ed9434". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-pxtc5.
If you don't see a command prompt, try pressing enter.

root@go-app-67bcfbcc98-xltgn:/usr/local/bin# 
root@go-app-67bcfbcc98-xltgn:/usr/local/bin# ls
FlameGraph-master  alp  calicoctl  iredis  litecli  pprof  redis-stable  websocat
root@go-app-67bcfbcc98-xltgn:/usr/local/bin# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
65532          1       0  0 00:27 ?        00:00:00 /usr/bin/qemu-x86_64 /ko-app/test /ko-app/test
root          20       0  1 00:39 pts/0    00:00:00 /usr/bin/qemu-x86_64 /bin/bash /bin/bash
root          36       0  1 00:39 pts/0    00:00:00 /usr/bin/qemu-x86_64 /bin/bash /bin/bash
root         111      20  0 Dec07 ?        00:00:00 ps -ef

# curl したらアクセスできるので同じポートスベースを共有しています
root@go-app-67bcfbcc98-xltgn:/usr/local/bin# curl localhost:8080
Hello, Docker! <3root@go-app-67bcfbcc98-xltgn:/usr/local/bin# 
root@go-app-67bcfbcc98-xltgn:/usr/local/bin# 

kubectl debug による Volume Mount のコピーが対応されていないようで /ko-app/test を直接みるのはできませんでした。残念。

次に dlv でプロセスに接続してみます。 公式には dlv が入ってるとありましたが入ってないので入れます。 (バグっぽいので issue を立てた

root@a51e0a534a6d:/usr/local/bin# ~/.gvm/gos/go1.17.6/bin/go install github.com/go-delve/delve/cmd/dlv@latest

その後 dlv で接続してみましたが、function not implemented で接続できませんでした。

root@go-app-67bcfbcc98-xltgn:~/.gvm/bin# ps aux | grep ko | grep -v grep
65532          1  0.0  0.2 867528 22352 ?        Ssl  00:27   0:00 /usr/bin/qemu-x86_64 /ko-app/test /ko-app/test
root@go-app-67bcfbcc98-xltgn:~/.gvm/bin# dlv attach 1    
could not attach to pid 1: function not implemented

issue をみると M1 mac での qemu では、ptrace がエミュレートされていないようで、ptrace に依存する dlv も動かないようです。残念。

うう・・・、ローカルエミュレートも厳しく、kubectl debug が新しい k8s しか対応していないので一旦ここまでにしておきます。