雑記帳

整理しない情報集

更新情報

k3s(k8s)のメモ書き(Tips)

公開日:

カテゴリ: ソフトウェア

Docker Composeからk3sに移行した際にハマったポイントや知ってると便利だったことを残しておきます。

k3sの再起動

コントロールブレーンを再起動する場合は、普通にk3sサービスを停止すればOKです。他のコンテナは稼働したままとなります。

# 停止
sudo systemctl stop k3s
# 起動
sudo systemctl start k3s

コンテナやネットワークを含めてk3sを丸ごと停止するには、インストール時に実行したスクリプトで生成される以下のコマンドを実行します。再起動時は普通にk3sのサービスを起動すればOKです。

# 停止
k3s-killall
# 起動
sudo systemctl start k3s

インストールスクリプトを用いずにk3sを実行している場合は、インストールスクリプトのソース(create_killall()関数)を参考に停止させていくことになると思われます。。。(未検証)

肥大化したstate.dbの掃除

k3sを使い続けていると、全リソースの状態を格納しているstate.dbが肥大化していきます。論理的には自動でクリーンされているようですが、物理的にはクリーンされないので、ファイルサイズが気になる場合は時々手動でVACUUMクエリを投げる必要があります。

実行にはコントロールブレーンの停止が必要です。Podなどを止める必要はありません。

# コントロールブレーンの停止
sudo systemctl stop k3s
# VACUUMクエリ実行
sudo sqlite3 /var/lib/rancher/k3s/server/db/state.db "VACUUM;"
# 必要に応じてWALの書き戻し(通常は不要)
sudo sqlite3 /var/lib/rancher/k3s/server/db/state.db "PRAGMA wal_checkpoint(TRUNCATE);"
# コントロールブレーンの起動
sudo systemctl start k3s

デバッグ方法

トラブルの際にscratchイメージやdistrolessイメージを用いていてコンテナのシェルに入れない場合、kubectl debugコマンドでエフェメラルコンテナをアタッチして入ります。

kubectl debug -it Pod名 --image=busybox -- /bin/sh

プロセス名前空間を共有するには--target=コンテナ名オプション、特権が必要な場合は--profile=sysadminオプションを追加します。これらのオプションを用いて、/proc/$PID/root(大抵は/proc/1/root)から対象のコンテナのファイルシステムに入れます。

kubectl cpコマンドについて

kubectl cpコマンドはdocker cpコマンドと異なり、コンテナ内でtarコマンドが使えない場合は使用できません。scratchイメージやdistrolessイメージではcatコマンドも使えないことが多いため、上のkubectl debugコマンドを使うことになります。

ファイルからConfigMapのmanifestを作成

kubectl createでConfigMapを作成している場合、上書き更新ができないため一度削除(kubectl delete)する必要があります。そのため、早めにmanifestファイルを用いる方法に切り替えたいところです。

kubectl getコマンドには、コマンドの実行結果をyaml形式で出力するオプションがあり、そのままmanifestとして使用することができます(出力結果をそのままkubectl apply -fに渡すことが可能)。

kubectl get cm ConfigMap名 -o yaml > configmap.yaml

さらに応用として、--dry-runオプションで予行実行が行えるため、以下のコマンドで既存ファイル/ディレクトリから直接ConfigMapのmanifestを作成することができます。

kubectl create cm ConfigMap名 --from-file=ファイルパス --dry-run -o yaml > configmap.yaml

組み込みCoreDNSの設定カスタマイズ

k3s組み込みのCoreDNSのDeploymentとCorefileは以下のような設定(抜粋)になっています(ソース)。

spec:
  template:
    spec:
      containers:
      - name: coredns
        volumeMounts:
        - name: custom-config-volume
          mountPath: /etc/coredns/custom
          readOnly: true
      volumes:
        - name: custom-config-volume
          configMap:
            name: coredns-custom
            optional: true
.:53 {
    # (中略)
    import /etc/coredns/custom/*.override
}
import /etc/coredns/custom/*.server

ということでkube-system名前空間にcoredns-customというConfigMapを作成し、.:53 {}内に追加したい設定は.overrideで終わるファイル名、外側に追加したい設定は.serverで終わるファイル名の設定ファイルを追加することでカスタマイズできます。

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns-custom
  namespace: kube-system
data:
  config.override: |
    # .:53 {} 内に追加したい設定
  config.server: |
    # 外側に追加したい設定

k8sとは直接関係ありませんが、内部用DNSでカスタムドメインへのrewriteを行う場合、rewriteの記述の最後にanswer autoをつけて、リクエスト元のドメインの応答を返すようにしましょう。

NetworkPolicyを指定している場合の名前解決

NetworkPolicyを設定している場合、そのままではDNSサーバへのアクセスもブロックされます。クラスタ内部への名前解決を行うには、kube-system名前空間内のk8s-app: kube-dnsラベルの53番ポートへの外向きアクセスが許可されている必要があります。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: # (略)
spec:
  podSelector: # (略)
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

NetworkPolicyでのポート指定

NetworkPolicyはPodに対するポリシーを設定しているため、Serviceでの変換後のポート番号ではなくPod側で公開しているポート番号を設定します。

(例) Podで公開しているポートが8080の場合、Serviceで8080から80に変換していたとしても、NetworkPolicyで指定するポート番号は8080

Podから組み込みTraefikへのアクセス許可

組み込みTraefikのポートはhttpが8000、httpsは8443がPodで公開されています。

NetworkPolicyでのKubernetes APIへのアクセスを許可

k3sではKubernetes APIはPodではなくホストネットワーク上で動作しているため、selectorでの指定でアクセス許可をすることができません。NodeのIPをCIDR指定で許可することになります。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: # 略
spec:
  podSelector: # 略
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: ノードのIP/32

NodeのIPはkubectl getの出力モードで-o wideを指定すると確認できます。

kubectl get nodes -o wide

kubectlのTab補完

kubectlにはTabキーによるコマンド補完機能が備わっており、サブコマンドだけでなく名前空間やPod名の補完も可能です(bash/zsh/fish)。そこそこ重いですが。。。

以下を各種ターミナルの設定ファイルに追記することでTab補完が使えるようになります。

# bashの場合
source <(kubectl completion bash)
# zshの場合
source <(kubectl completion zsh)
# fishの場合
kubectl completion fish | source

リダイレクトで直接追記する場合は以下のような感じになります。

# bashの場合
echo "source <(kubectl completion bash)" >> ~/.bashrc
# zshの場合
echo "source <(kubectl completion zsh)" >> ~/.zshrc
# fishの場合
echo "kubectl completion fish | source" >> ~/.config/fish/config.fish

カテゴリ: ソフトウェア