見出し画像

kubectlをcronから起動するときの注意

はじめに

こんにちは。インフラエンジニアの北野です。

kubectlは、kubernetesを管理するためのコマンドラインツールですが、
運用の中でcronからkubectlを含むスクリプトを定期実行したいときってありますよね。

今回は、kubectlを含むShellスクリプトをcronから起動したとき、想定外のエラーが出たので、 その原因と対策を共有したいと思います。

前提となる環境

  • コンテナ基盤:EKS

  • OS:amazon linux2

忙しい人の為に先に結論

kubectl含むスクリプトをcronから実行する場合、 /etc/crontabのPATH定義を以下のように設定することを推奨します。

PATH=/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
  1. PATHに/usr/local/binを追加する

  2. 追加する/usr/local/binは先頭(一番左)に定義する

この2点がエラーを回避するポイントとなります。

cronから起動したスクリプトからkubectlを実行すると「command not found」が発生。

とある要件で、EKSのコンテナの監視スクリプトを作成することに。 起動方法はお手軽なcron、言語はshellを採用しました。

スクリプトを作成し、単体テストでは正常に動作することを確認しました。 続いて結合テストでcron実行したところ、異常終了してしまいました。

出力されたエラーは以下のとおりです。

xxxx.sh: line xx: kubectl: command not found

「command not found」の発生原因。

shellログインして実行した場合は、正常に動作するのに、cron実行の場合はコマンドが見つからないのは何故でしょうか。

/etc/crontab内には下記のように実行シェルとパス等の環境変数が設定されています。

# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin

cronから起動するスクリプトのコマンドがパスのどれかに含まれている場合は問題ないのですが、 kubectlは/usr/local/bin/内に置かれるので、コマンドが見つかりません。

PATHに追加設定してみると、amazonlinuxの場合は想定外のエラーが発生

対応として、まずは単純にスクリプトの初期処理で以下のようにPATHを追加設定しました。

PATH=$PATH:/usr/local/bin

よしこれでkubectlのPATHが通ったので、うまくいくだろうとcron実行すると、エラーで異常終了しました。。

出力されたエラーは以下のとおりです。

usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

aws help
aws <command> help
aws <command> <subcommand> help
aws: error: argument operation: Invalid choice, varid choices are:

create-cluster | delete-cluster
describe-cluster | describe-cluster
list-clusters | list-updates
update-cluster-version | update-kubeconfig
wait | help
Unable to connect to the server: getting credentials: exec: executable aws failed with exit code 2

事象はawscliのコマンドパラメーター誤り??

awscliのコマンドパラメーター誤りの発生原因

これの原因は、PATHの定義順番の誤りと、想定外のawscliコマンドの実行によるものでした。

普通、PATHの定義を追加をするときは以下のようにするかと思います。

PATH=$PATH:追加するディレクトリ名

まずはこれがNGでした。

awscliは公式の手順に沿って導入すると以下のディレクトリに配置されます。

/usr/local/bin/aws

awscliの導入について:https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

しかし、実はamazon linuxの場合は、デフォルトで/usr/binや/binの配下にもawscliのモジュールが存在していたのです。 そしてこのモジュールはメンテナンスされず、古いバージョンのままとなってしまっていました。

その為、固定観念に囚われてPATH=$PATH:/usr/local/bin などとしてしまうと、もともとのPATHに設定されている/bin配下のawsコマンドが優先して実行されてしまいます。

そして、私の環境の/bin/awsのawscliはバージョン1.16.102で、残念ながらこのバージョンはaws eks get-tokenのコマンドオプションがありませんでした。 その結果、get-tokenのコマンドオプションが無く、configに設定しているEKS認証用のtoken取得コマンドに失敗し、kubectlの実行に失敗しました。

configの設定について:https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-kubeconfig.html

configに記述した認証の記述部分を抜粋します。

ここで設定しているcommandは実行時のPATHの設定に従って、どのディレクトリに配置されたawscliモジュールが実行されるかが決まります。

users:
- name: arn:aws:eks:$region_code:$account_id:cluster/$cluster_name
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      command: aws
      args:
        - --region
        - $region_code
        - eks
        - get-token
        - --cluster-name
        - $cluster_name

まとめ

kubectlをcronから起動したときに想定外のエラーを出さないためには、 /etc/crontabのPATH定義を以下のように設定することを推奨します。

PATH=/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

こうしておけば、/usr/local/bin配下のkubectlやawsが優先して実行されます。

すべてのユーザのcron定義にこの変更を反映させたくない場合は、/var/spool/cron/ユーザー名のファイルに 以下を記述しましょう。

PATH=/usr/local/bin:$PATH

さらに影響範囲を極小化した場合は、Shellスクリプト自体や共通環境設定ファイルに記述すると良いですね。


【おわせて読みたい関連記事】


執筆者プロフィール:北野 啓史
ITベンダーで13年間インフラエンジニアとして金融、人材などのお客様のITシステムの開発に携わってきた。
SHIFTには2021年に入社し、現在はコンテナ基盤のインフラ設計・構築を担当している。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/

PHOTO: UnsplashFaye Yu