5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ひとりでkubernetesを中心にAdvent Calendar 2021

Day 1

[EKS] kubectlを高速化する

Last updated at Posted at 2021-12-02

(初日くらい少しは実のある記事を書きたい)

前置きが少し長くなったのでせっかちな人は実装のとこまで飛ばしてください

前置き

AWSのmanaged kubernetesサービス、EKS
kubernetes運用経験がある人がEKSを触ると

kubectlが遅い…

割と皆さん感じてるかと思います
私は入力補完の遅さで特にストレスを感じていました

この遅さの理由はEKSのクラスタ認証にあって
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/managing-auth.html

クラスタにアクセスするためには、まずAWSにそのためのtokenを発行してもらう必要があるからです

ほとんどの人は、eksクラスタにアクセスするためのkubeconfigを作成する際に
aws eks update-kubeconfig
このコマンドを利用しているかと思います
そうすると出来上がるkubeconfigの一部が

- name: my-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-1
      - eks
      - get-token
      - --cluster-name
      - my-cluster
      command: aws
      env:
      - name: AWS_PROFILE
        value: my-profile
      provideClusterInfo: false

このような形になっているはずです
これはつまり、kubectlの認証に、 aws eks get-token を使用しているということで、kubectlコマンドを実行するごとに(入力補完の一部にも)このget-tokenを実行しているということです
そしてこのget-tokenはkubectlの実行より時間がかかっています(体感調べ)

高速化を試みる

で、この aws eks get-token 以下の内容が返ってきています

{
  "kind": "ExecCredential",
  "apiVersion": "client.authentication.k8s.io/v1alpha1",
  "spec": {},
  "status": {
    "expirationTimestamp": "2021-12-02T17:05:31Z",
    "token": "**************************************************"
  }
}

expirationTimestamp がおよそ15分後に設定されているのがわかります
どうやらこのtokenは15分有効らしいです
なので、kubectlするごとにget-tokenしなくても、1回get-tokenしたらその後15分間はこのtokenを使えばよさそう

今回はこのtokenをファイルに保存して、kubectl実行時にtokenの期限までn秒を切っていたら再びget-tokenする、という方法にします

実装

ざっくりで!

#!/bin/bash
# 引数
# p : aws profile
# c : cluster name

# jq使わせてくださいすいません
if ! type jq >/dev/null; then
    echo "sorry, plz install jq ;)"
    exit 1
fi

CACHE_DIR=~/.kube/cache # tokenファイルを保存するディレクトリ(お好きな場所で)
AWS_REGION=ap-northeast-1 # 雑に固定
REORDER_BEFORE=60 # キャッシュの有効期限がこの秒を割ると再取得する

while getopts c:p: OPT
do
    case $OPT in
        c) CLUSTER_NAME=$OPTARG ;;
        p) AWS_PROFILE=$OPTARG ;;
    esac
done

if [ -z ${CLUSTER_NAME} ] || [ -z ${AWS_PROFILE} ]; then
    echo "reqired args -c [cluster-name] -p [aws-profile]"
    exit 1
fi

if [ ! -d ${CACHE_DIR} ]; then
    mkdir -p ${CACHE_DIR}
fi

CACHE_FILE=${CACHE_DIR}/${AWS_PROFILE}:${CLUSTER_NAME} # [profile名]:[クラスタ名] という形で保存(お好きな形で)
if [ -e ${CACHE_FILE} ]; then
    # 以下のdateコマンドが絡むものはbsdのdateでのみ有効なので
    # linuxや、macでもgdateとかにエイリアス貼ってる場合はコメントをヒントにしていい感じに
    # 他にもTZとか環境によっては変更する必要があるかも
    NOW_UNIX=$(date -j -f %Y-%m-%dT%H:%M:%SZ $(date -u +%Y-%m-%dT%H:%M:%SZ) +%s) # 現在時刻のunixtimeを取得
    EXPIRE=`cat ${CACHE_FILE} | jq -r '.status.expirationTimestamp'` # キャッシュファイルから有効期限を取得
    EXPIRE_UNIX=`date -j -f "%Y-%m-%dT%H:%M:%SZ" ${EXPIRE} +%s` # 有効期限をunixtimeに変換
    
    CACHE_TTL=`expr ${EXPIRE_UNIX} - ${NOW_UNIX}`
    
    if [ ${CACHE_TTL} -lt ${REORDER_BEFORE} ]; then
        aws eks get-token --cluster=${CLUSTER_NAME} --profile=${AWS_PROFILE} --region=${AWS_REGION} >${CACHE_FILE}
    fi
else
    aws eks get-token --cluster=${CLUSTER_NAME} --profile=${AWS_PROFILE} --region=${AWS_REGION} >${CACHE_FILE}
fi

cat ${CACHE_FILE}

このようなシェルスクリプトを作成し、実行権限を付与してパスの通る場所に置きます
今回は、 eks-get-token-use-cache とします

作ったら、先程のkubeconfig

- name: my-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-1
      - eks
      - get-token
      - --cluster-name
      - my-cluster
      command: aws
      env:
      - name: AWS_PROFILE
        value: my-profile
      provideClusterInfo: false

この部分を、以下のように変更します

- name: my-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - -p
      - my-profile
      - -c
      - my-cluster
      command: eks-get-token-use-cache
      provideClusterInfo: false

ここまで設定すれば、kubectl実行時にtokenのキャッシュファイルを作成し、期限切れ直前に更新する、という動きになります
当然ですが、tokenを更新する時だけは遅いままです

その後

人間というのは贅沢なもので、これに慣れると今度は約15分に1回訪れる更新が気になってしまいます
なのでこの15分を伸ばしてやろうと思い、色々調べてみたのですが現状では無理みたいです
https://github.com/aws/aws-sdk-go/issues/2167
ので、そこだけは耐えましょう
ちなみに、 aws eks get-token ができるまでは aws-iam-authenticator というものが使われていたのですが、こっちのほうが少し速いので(環境差あるかも?)、そっちを使えば更新も少し速くなります

あとは、無効なtokenを誤ってキャッシュしてしまうと期限切れまで延々それを使おうとするなどちょっとした課題もありますが、そっとファイルを消してください
その他不具合があったらごめんなさい

5
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?