はじめに
Amazon EKSで作成したクラスタに対してkubectlコマンドで接続する際、kubeconfigファイル(~/.kube/config等)を記述する必要がありますが、AWSの公式ドキュメントに記載されている手順は以下のように手作業ベースとなっています。
- AWS CLI (
aws eks describe-cluster
) を使用して、EKSクラスタの情報(エンドポイントURL、認証キー、等)を取得する。 - 空のkubeconfigファイルを作成して、ドキュメントページに掲載されているテンプレートをコピペする。
- テンプレート中のプレースホルダー(例:<endpoint-url>)を「手順1.」で取得した情報に置き換える。
EKSクラスタの作成を何度も行うような場合1、これは結構な手間になります。
一方、Azure Kubernetes Service (AKS)では、Azure CLIの az aks get-credentials
コマンドを一発叩くだけでkubeconfigファイルの設定が行えます。
EKSでも同じようなコマンドがあったらなぁ~、と思ったので、Go言語&AWS-SDKの勉強がてらに作ってみました。
コードはこちらを参照:
https://github.com/hideakiaoyagi/kubeconfig-eks
使い方
基本的なコマンド構文は以下の通りです。
$ kubeconfig-eks --config <kubeconfigファイルのパス> --name <クラスタ名> --region <リージョン>
--config
オプションの省略時は ~/.kube/config
を参照します。
--name
および --region
オプションは省略できません。2
また、kubeconfigファイル中にEKSクラスタ情報を書き込む際、各データの「name」キーは以下のような名前で設定されます。
clusters:
name: eks-cluster
cluster: ...
users:
name: eks-user
user: ...
contexts:
name: eks-cluster
context: ...
これらの値を変更したい場合は、それぞれ --config-key-cluster
、--config-key-user
、--config-key-context
で指定します。
コード解説
main.go
コマンドラインツール作成支援ライブラリである urfave/cli
パッケージを使用しました。
https://github.com/urfave/cli
urfave/cli
は今風(?)の「コマンド サブコマンド --引数
」形式のCLIも作成できる高機能なパッケージなのですが、今回は単純な「コマンド --引数
」の作りにしました。
(Azure CLIのコマンド風に kubeconfig-eks get-credentials --name...
とかにしても良かったのですが、無駄に長くなるので止めました)
sub-aws-eks.go: AWS-SDKを使用したEKSクラスタ情報取得
情報取得には、AWS SDK for Goの関数 DescribeCluster()
を使用します。
https://docs.aws.amazon.com/sdk-for-go/api/service/eks/#EKS.DescribeCluster
この関数の使い方は、
- 抽出条件(今回の場合は「クラスタ名」のみ)を指定した構造体を食わせて
- 抽出結果を構造体で受け取る
というもので、特にハマる点はありませんでした。
sub-yaml.go: kubeconfigファイルの読み書き (YAMLデータのハンドリング)
YAMLデータをハンドリングするために gopkg.in/yaml.v2
パッケージを使用しました。
https://gopkg.in/yaml.v2
https://github.com/go-yaml/yaml/tree/v2
実は、この部分が今回の一番苦労したところでした。
gopkg.in/yaml.v2
パッケージでYAMLデータを扱う際、データの持たせ方には2通りの方法があります。
- YAMLデータの構造に合わせて予め構造体を定義しておく
- 構造が定まっていないYAMLデータを格納するために、interface{}型の要素を持つMapの構造体を用いる
kubeconfigファイルのYAML構成は、EKS、AKS、GKE、minikube、etc.へ接続する場合で少しずつ異なっています。
どのYAML構成であっても読み書きできるよう、今回は後者を採用しました。
基本的に各データは map[interface{}]interface{} 型となりますが、第1階層にある「clusters:
」「users:
」「contexts:
」は直下に配列データを持つため []interface{} 型となります。(それらの配下は map[interface{}]interface{} 型となる)
・・・と文章で書いても非常に分かり辛いですね。
下記の記事などを参考にさせて頂きました。
https://qiita.com/yamasaki-masahide/items/d6e406c4c11d5870a1c6
おわりに
Go言語のセオリー(プロジェクト構成、エラー処理、etc.)が全く分かっていないので全然イケてないコードだと思いますが、所詮「習作」なので大目に見て下さい。
「こうしたらいいよ」というコメントは大歓迎です!(笑)