kubernetes には kubectl というコマンドがあり普段のオペレーションはそちらでやることが多いと思いますが、サーバから kubernetes をコントロールしたいというニーズもあるとも思います。
kubernetes には REST API が用意されているのでそれにアクセスすれば良いんですが、どうやって認証すればいいのか迷ったのでメモを残しておきます。
認証
いくつかの認証方式が用意されています。
- X509証明書
- BASIC認証
- TOKEN
- Service Account
- OpenID
今回は TOKEN 方式でやってみます。
トークン取得
トークンや証明書は Pod の中に入って /var/run/secrets/kubernetes.io/
にあります。手動で取るのはさすがにかったるいので、下記コマンドを叩きます。
$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') \
| grep -E '^token' | cut -f2 -d':' | tr -d '\t')
これでトークンが取得できるはずです。
APIサーバのIP
次に curl で叩く先のIPアドレスを取得します。以下のコマンドで取得できるんですが、複数のクラスタを設定している場合は複数出てしまうので注意してください。
kubectl config view | grep server | cut -f 2- -d ":" | tr -d " "
GKE だとコントロールパネルの以下の部分で確認ができます。
アクセスしてみる
TOKEN=$(kubectl describe secret $(kubectl get secrets | \
grep default | cut -f1 -d ' ') | \
grep -E '^token' | cut -f2 -d':' | tr -d '\t')
curl https://example.com/api/v1/namespaces/default/pods \
--header "Authorization: Bearer $TOKEN" --insecure
これで Pod の一覧が取得できるはずです。最高ですね。あとは、REST API のリファレンスを見て kubernetes と仲良くなってください。なお、バージョンによって使える API と使えない API があるので注意してください。
kubectl proxy というやり方も
公式ではこちらをオススメしてます。
kubectl proxy --port=8080 &
$ curl http://localhost:8080/api/
{
"versions": [
"v1"
]
}
クライアントライブラリ
クライアントライブラリも各言語ごとにいくつかあります。
公式では Go と Python ですね。Rubyだと abonas/kubeclient あたりが良さそうです。
abonas/kubeclient
Rubyのgem abonas/kubeclient
を使ってAPIにアクセスしてみます。前述したTOKENの取得ができていれば環境変数などにブチ込んで接続するだけです。
auth_options = {
bearer_token: ENV['K8S_API_TOKEN']
}
client = Kubeclient::Client.new(
"https://#{ENV['K8S_API_HOST']}/api/", 'v1', auth_options: auth_options
)
client.get_pods
ただ、これだけだとSSLでエラーが出ると思います。kubernetesは独自の証明書を使っているため、そのままだと接続できないからです。 実際にコマンドを実行しようとすると、 KubeException: SSL_connect returned=1 errno=0 state=error: certificate verify failed
こんな感じのエラーが出ます。
証明書の設定
OpenSSL::SSL::VERIFY_NONE
にする手もありますがオススメはしません。
まず、接続用の証明書を作ります。
openssl genrsa -aes128 2048 > client.key
openssl req -new -key client.key > client.csr
openssl x509 -in client.csr -days 365000 -req -signkey client.key > client.crt
openssl rsa -in client.key -out client.key
次にkubernetesの証明書を取得します。Podの中の /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
にあります。
最後に abonas/kubeclient
で接続します。
auth_options = {
bearer_token: ENV['K8S_API_TOKEN']
}
ssl_options = {
client_cert: OpenSSL::X509::Certificate.new(File.read(Rails.root.join("secrets", "k8s_client.crt"))),
client_key: OpenSSL::PKey::RSA.new(File.read(Rails.root.join("secrets", "k8s_client.key"))),
ca_file: Rails.root.join("secrets", "k8s_ca.crt"),
verify_ssl: OpenSSL::SSL::VERIFY_PEER
}
client = Kubeclient::Client.new(
"https://#{ENV['K8S_API_HOST']}/api/", 'v1',
auth_options: auth_options,
ssl_options: ssl_options
)
client.get_pods
以上で接続できるようになります。