kran 文件

常見問題

工具不在 PATH 上

$ kran deploy
ERROR: krane is not on PATH. Install it with `gem install krane`, or add it to a Gemfile and set krane.command to `bundle exec krane`.

檢查在第一行指令之前就做完,而且會一次列出所有缺的工具。其他提示:

工具 提示
docker https://docs.docker.com/get-docker/ 安裝
kubectl https://kubernetes.io/docs/tasks/tools/ 安裝
ejson gem install ejson(krane 本來就依賴它)或 brew install ejson

設成 krane.command: bundle exec krane 時,你看到的可能是 bundle is not on PATH:kran 檢查的是 它實際啟動的那支程式。kran deploy -P 不需要 docker,--dry-run 則完全跳過檢查。

kran 推導不出 image tag

$ kran deploy
ERROR: Git could not provide an image tag in /srv/build: Command failed (exit 128): git rev-parse HEAD
fatal: not a git repository (or any of the parent directories): .git
Pass --version to set the tag explicitly.
$ kran deploy --version 2024-06-01-1

Image tag

tag 為什麼多了 uncommitted

因為 git status --porcelain 有輸出。後綴是十六位隨機十六進位字元,不是雜湊。image 裡真的含有那些 變更,因為 kran 從工作目錄建置;kamal 預設不是這樣。見 Image tag

krane 不肯部署到我的 namespace

krane 把 defaultkube-systemkube-public 當成受保護的,換一個 namespace:

$ kubectl --context prod-east create namespace storefront
namespace/storefront created
kubernetes:
  context: prod-east
  namespace: storefront

這是 krane 的規則,kran 只是原樣把 namespace 傳過去。

registry 密碼一定要寫進 kran.yml 嗎

不用。不設 registry.usernameregistry.password,kran 就跳過 docker login,推送直接用這台 機器上 docker login 過的帳號。只有事先沒人登入過的環境(例如 CI)才需要兩個都設。

Secret ejson-keys not found

krane 是在叢集裡解 secrets.ejson,私鑰得放在那邊:

$ kubectl --context prod-east --namespace storefront \
>   create secret generic ejson-keys \
>   --from-literal=<公鑰>=<私鑰>
secret/ejson-keys created

要用 create 不要用 apply,否則會被 krane 的 prune 刪掉。見 機密資料

這跟 registry.password: { ejson: ... } 是兩回事,後者由 kran 在本機用 ejson 執行檔和 /opt/ejson/keys/<公鑰>EJSON_KEYDIR 裡的金鑰解開。

遠端 daemon 的多架構建置失敗

設了 builder.remote 時,兩個平台得由同一台 daemon 建完,這需要 binfmt/QEMU 加 containerd image store,或是每個架構各掛一個 node 的 buildx builder。

$ kran build details
DOCKER_HOST=ssh://builder@build.internal docker version
DOCKER_HOST=ssh://builder@build.internal docker buildx ls
NAME/NODE       DRIVER/ENDPOINT   STATUS    BUILDKIT   PLATFORMS
default*        docker
 \_ default      \_ default       running   v0.19.0    linux/amd64

PLATFORMS 只列出一個架構的話,就只建一個:

builder:
  arch: amd64
  remote: ssh://builder@build.internal

遠端 builder

exec 的旗標被 kran 吃掉

在指令前面補一個單獨的 --,否則 -e 會被當成 kran 的選項:

kran exec -- bin/rails runner -e production 'puts Rails.env'

沒有符合 selector 的執行中 pod

$ kran exec bin/rails db:migrate
No running pod matches app=storefront

kran exec 需要一個符合 app.selector 且階段是 Running 的 pod。先確認 krane 模板裡的 label 跟 selector 對得上(kran details 會列出 pod),再確認它們真的在執行。沒在執行的 pod,kran logs 還是讀得到。

kran logs 幾乎沒東西

不給 -n 時,用了 selector 的 kubectl 每個 pod 只顯示最後 10 行。

kran logs -n 500
kran logs --since 1h

在 bundle exec 底下跑 kran

kran 在 Bundler.with_unbundled_env 裡執行每個外部指令,所以 krane、ejson、docker、kubectl、git 啟動前,RUBYOPTBUNDLE_GEMFILE 都已經被拿掉,否則 krane 會跑去對 kran 的 Gemfile 解相依。

所以 krane 裝在全域時 bundle exec kran deploy 可用;krane 在另一個 bundle 裡時,只要指明也可用:

krane:
  command: BUNDLE_GEMFILE=deploy/Gemfile bundle exec krane

你自己 export 的環境變數不受影響。用 kran version 確認。

可以只看指令、不實際執行嗎

kran deploy --dry-run
kran build push --dry-run
kran logs --dry-run

--dry-run 每個指令都支援,而且不會印出密碼。

kran 會改到我目前的 kubectl context 嗎

不會。它在每個 kubectl 指令上帶 --context--namespace;有設 kubernetes.kubeconfig 時再加上 KUBECONFIG= 前綴。

還可以直接用 krane 和 kubectl 嗎

可以。從 kran deploy --dry-run 把前綴複製走:

KUBECONFIG=/home/dana/.kube/prod-east.yml \
  kubectl --context prod-east --namespace storefront get ingress

kran 不存狀態,也不裝任何 hook。