概要
Ruby で k8s の API をいろいろとコールしてみました
Pod の作成から削除、一覧の取得のサンプルを紹介します
また使用しているライブラリは k8s-client になります
環境
- macOS 10.14.5
- minikube v0.28.2
- Ruby 2.6.2p47
- k8s-client 0.10.0
準備
bundle init
vim Gemfile
gem "k8s-client"
bundle install --path vendor
クライアント作成
まずは API をコールするためのクライアントを作成します
vim app.rb
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
bundle exec ruby app.rb
k8s
の config ファイルを指定するのが一番簡単だと思います
それ以外にもエンドポイントを指定する方法もあります
API とリソースの一覧表示
まずはテストとして k8s の API の一覧を取得してみます
vim app.rb
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
client.apis.each { |a|
puts a.api_version
a.api_resources.each { |r|
puts " #{r.name}"
}
}
api_version
で API の一覧を取得しています
更に api_resources
で API に紐づくリソースの一覧も取得しています
この API 名とリソースは API をコールする際に利用します
Pod 作成
基本は YAML で定義した情報はハッシュに落とし込めば OK です
あとはリクエストするパスとメソッドの組み合わせを指定します
vim app.rb
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
deployment = K8s::Resource.new(
apiVersion: 'extensions/v1beta1',
kind: 'Deployment',
metadata: {
name: 'redis-single',
namespace: 'default'
},
spec: {
replicas: 1,
template: {
metadata: {
labels: {
app: 'redis',
role: 'single'
}
},
spec: {
containers: [
{
name: 'single',
image: 'redis',
ports: [
{
containerPort: 6379
}
]
}
]
}
}
}
)
ret = client.api('extensions/v1beta1').resource('deployments').create_resource(deployment)
pp ret.to_json
リソースを作成する場合は K8s::Resource.new
を使います
これにハッシュを指定することでリクエスト用の JSON に内部的に変換してくれます
今回は redis コンテナを立ち上げる Deployment になっています
ポイントは metadata.namespace
で namespace を指定する点です
default
でも指定する必要があります
これを指定しないと POST /apis/extensions/v1beta1/deployments => HTTP 405 Method Not Allowed: the server does not allow this method on the requested resource (K8s::Error::MethodNotAllowed)
となり本来アクセスするパスの /apis/extensions/v1beta1/namespaces/{namespace}/deployments
にアクセスしてくれません
型の指定にも注意しましょう
レプリカの数やポート番号は整数で指定する必要があります
あとはちゃんとパラメータの階層や構造を間違えないようにしましょう
YAML からハッシュに落とし込む際に自分は階層がずれて K8s::Error::Invalid
が発生しました
レスポンスは実際にリクエストした Deployment のリソース情報が返ってきます (長いので省略)
以下のように Deployment, ReplicaSet, Pod が作成できていれば OK です
kubectl get deploy,rs,po
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/redis-single 1/1 1 1 54s
NAME DESIRED CURRENT READY AGE
replicaset.extensions/redis-single-864f5b6474 1 1 1 54s
NAME READY STATUS RESTARTS AGE
pod/redis-single-864f5b6474-hwxxj 1/1 Running 0 54s
Pod 作成 (yaml を直接使う)
直接 YAML ファイルを使用する方法もあります
特に YAML に変更がない場合などはこっちの方法を使ったほうが簡単にできると思います
vim redis_deployment.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis-single
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
app: redis
role: single
spec:
containers:
- name: single
image: redis
ports:
- containerPort: 6379
YAML の場合も metadata.namespace
を指定するようにしてください
vim app.rb
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
resources = K8s::Resource.from_files('./redis_deployment.yml')
resources.each { |r|
p client.create_resource(r)
}
これで先ほどと同じリソースが作成されます
Service 作成
作成した Pod を外部からアクセスできるようにしてみます
vim app.rb
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
service = K8s::Resource.new(
apiVersion: 'v1',
kind: 'Service',
metadata: {
name: 'redis-single',
namespace: 'default'
},
spec: {
type: 'NodePort',
selector: {
role: 'single'
},
ports: [
{
protocol: 'TCP',
port: 6379,
targetPort: 6379
}
]
}
)
ret = client.api('v1').resource('services').create_resource(service)
pp ret.to_json
これも Deployment と同じで namespace を指定します
あとは YAML をそのままハッシュに変換すれば OK です
アクセスするパスは client.api('v1').resource('services')
になります
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 122d
redis-single NodePort 10.107.200.3 <none> 6379:32503/TCP 16s
redis-cli -h $(minikube ip) -p 32503 info server
作成したリソースの一覧取得
kubectl get
をやってみます
vim app.rb
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
pods = client.api('v1').resource('pods', namespace: 'default').list
pods.each { |p|
p p.metadata.name
}
deployments = client.api('extensions/v1beta1').resource('deployments', namespace: 'default').list
deployments.each { |d|
p d.metadata.name
}
replicasets = client.api('apps/v1').resource('replicasets', namespace: 'default').list
replicasets.each { |r|
p r.metadata.name
}
services = client.api('v1').resource('services', namespace: 'default').list
services.each { |s|
p s.metadata.name
}
各リソースごとに指定可能な API バージョンの組み合わせが決まっているので冒頭で紹介した API とリソースを表示するスクリプトなどで確認してください
とりあえず metadata.name
だけ指定していますがそれ以外にも取得できます
K8s::Resource
クラスのインスタンスになります
後処理
kubectl delete svc redis-single
kubectl delete deploy redis-single
Ruby からやる場合は以下の通りです
require 'k8s-client'
client = K8s::Client.config(
K8s::Config.load_file(
File.expand_path '~/.kube/config'
)
)
p client.api('extensions/v1beta1').resource('deployments', namespace: 'default').delete('redis-single')
p client.api('apps/v1').resource('replicasets', namespace: 'default').delete('redis-single-57b6f5f7cb')
p client.api('v1').resource('pods', namespace: 'default').delete('redis-single-57b6f5f7cb-smx27')
p client.api('v1').resource('services', namespace: 'default').delete('redis-single')
ちゃんとすべてのリソースごとに削除する必要があります
最後に
k8s の API を Ruby から操作してみました
ライブラリの使い方にもなりますがハッシュでリソースを定義してリソースごとに割り当てられた API バージョンにリクエストする感じで使えます
API を直接読んでみると kubectl
コマンドがどういうふうに実装されているかのイメージも付くと思います
0 件のコメント:
コメントを投稿