Help us understand the problem. What is going on with this article?

kubernetes REST API に外部から接続する

More than 1 year has passed since last update.

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 だとコントロールパネルの以下の部分で確認ができます。

gke.png

アクセスしてみる

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

以上で接続できるようになります。

zaru
basicinc
マーケティングとテクノロジーで社会のあらゆる問題を解決する集団
https://tech.basicinc.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした