LoginSignup
5
3

More than 3 years have passed since last update.

KubernetesのPod内からObjectを生成する

Posted at

kubernetes便利ですよね。

golangでkubernetesを操作するときはclient-goという便利なライブラリがあるので、基本的にはこれを見れば完結します。
しかし、最近CRD(Custom Resource Definition)という自作Objectを作成したときに色々ハマったので、記事として残しておきます。

Objectとは

要はDeploymentとかServiceとかのことです。
今回は簡単のために、Jobを使います。
適宜自分が使いたいものに変えてください。

CRDを使わない場合

1つ目の方法はclient-goを使うものです。
client-goは名前そのままでkubernetesと通信をするためのクライアントのライブラリです。
以下のコードは簡単なJobを起動するためのコードです。

package main

import (
    "log"

    batchv1 "k8s.io/api/batch/v1"
    apiv1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
)

func main() {
    config, err := rest.InClusterConfig()
    if err != nil {
        panic(err.Error())
    }

    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    jobClient := clientset.BatchV1().Jobs("default")

    job := &batchv1.Job{
        // 省略...
    }

    job, err = jobClient.Create(job)
    if err != nil {
        log.Printf("Failed to create job: %v", err)
    }
}

この方法の欠点としては k8s.io/client-go/kubernetesに存在しているものしか作ることは出来ません。(DeploymentとかJobとか)
なので、もしCRD(Custom Resource Definition)を使う場合は上の方法では作成することは出来ないようです。(* 後ろの方にCRDでも実装する方法を書いています。)
その場合は以下の方法で作成してみてください。

CRDを使う場合

こっちもclient-goは使ってはいるのですが、メインはcontroller-runtime/pkg/clientです。

package main

import (
    "context"
    "fmt"
    "log"

    batchv1 "k8s.io/api/batch/v1"
    apiv1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/client-go/rest"
    clientPkg "sigs.k8s.io/controller-runtime/pkg/client"
)

func main() {
    // Kubernetesの設定
    config, err := rest.InClusterConfig()
    if err != nil {
        panic(err.Error())
    }

    scheme := runtime.NewScheme()
    batchv1.AddToScheme(scheme)
    option := clientPkg.Options{
        Scheme: scheme,
    }

    client, err := clientPkg.New(config, option)
    if err != nil {
        fmt.Println(err)
        return
    }

    job := &batchv1.Job{
        // 省略...
    }

    ctx := context.Background()

    err = client.Create(ctx, job)
    if err != nil {
        log.Printf("Failed to create job %v\n", err)
    }
}

気をつけるポイントとしては、

batchv1.AddToScheme(scheme)

の部分です。ここを適宜CRDのディレクトリのSchemeとして指定すると良いです。

ちなみにCRDを使って最初の方法で実装出来るらしいです。

参考記事

上の記事はちゃんと見たわけでは無いですが、自分でClientを自作して呼び出している感じですね。

地味にハマったポイント

今回は client-goのv11.0.0を使っていたんですが、以下のようなエラーが結構出てきました。
ググればすぐに解決策が出てくるのですが、念の為ここにも書いておきます。

# k8s.io/client-go/rest
../pkg/mod/k8s.io/client-go@v11.0.0+incompatible/rest/request.go:598:31: not enough arguments in call to watch.NewStreamWatcher
    have (*versioned.Decoder)
    want (watch.Decoder, watch.Reporter)

Go modulesを使っている場合は以下のようになると思います。
引用元: client-go/INSTALL.md

$ go get k8s.io/client-go@v11.0.0              # replace v11.0.0 with the required version (or use kubernetes-1.x.y tags if desired)
$ go get k8s.io/api@kubernetes-1.14.0          # replace kubernetes-1.14.0 with the required version
$ go get k8s.io/apimachinery@kubernetes-1.14.0 # replace kubernetes-1.14.0 with the required version

実装したリポジトリ

5
3
0

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
3