LoginSignup
6
1

More than 3 years have passed since last update.

cri-apiをGoで使ってみる

Last updated at Posted at 2019-12-05

この記事はKubernetes Advent Calendar 2019 その2の6日目の記事です。

kubernets/cri-apiをGoで使ってみたので、そのやり方を紹介したいと思います。

cri-apiとは

cri-apiはCRI(Container Runtime Interface)で規定されているI/Fの定義です。

KubernetesにはkubeletとHigh-LevelコンテナランタイムのI/Fを規定したCRIというものが存在します。

これはKubernetesに他のコンテナランタイムを組み込みやすくする事を目的に規定されているもので、CRIを満たしたコンテナランタイムであればKubernetsで動かす事ができます。

このcri-apiはprotocol bufferとgRPCで構成されており、
今回はprotocol bufferを使用してGoでcri-apiを使ってみてます。

試した環境

  • macOS Mojave 10.14
  • Go 1.13
  • protoc 3.11.1

protocol bufferのインストール

protocol bufferをインストールします。
macであればhomebrewでインストール可能です。

# インストール
brew update
brew install protobuf

# 確認
protoc --version #libprotc 3.11.1

Goで実装

今回やってみたのはclientとserverのプログラムを実装して、
client->serverにcri-apiで定義されている構造体を送って確認する、といったものになります。
(実装に当たってはprotocol buffers をGolangで使うを参考にさせて頂いています。)

以下実装していきますが事前に
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
しておきます。

まずはclientから実装していきます。

clientの実装

main.go
package main

import (
    "net"

    "github.com/golang/protobuf/proto"
    "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"


)

func main() {
    // cri-apiに定義されているPodSandbox構造体
    pod := &v1alpha2.PodSandbox{
        Id: "1000",
        Metadata: &v1alpha2.PodSandboxMetadata{
            Name:      "FakePod",
            Uid:       "123456789",
            Namespace: "System",
            Attempt:   0,
        },
        State:     v1alpha2.PodSandboxState_SANDBOX_READY,
        CreatedAt: 1,
    }

    // シリアライズ化
    out, err := proto.Marshal(pod)
    if err != nil {
        panic(err)
    }
    conn, err := net.Dial("tcp", "localhost:9000")
    if err != nil {
        panic(err)
    }

    // serverにデータを送信
    conn.Write(out)
}

cri-apiで定義されているPodSandbox構造体を作成。
構造体に適当な値を入れてシリアライズ化した後にlocalhost:9000宛に送信しています。
cri-apiPodSandbox以外にも多くの定義がありますが今回はPodSandboxを使っています)

次にserverを実装します。

serverの実装

main.go
package main

import (
    "bytes"
    "io"
    "net"
    "os"

    "github.com/golang/protobuf/jsonpb"
    "github.com/golang/protobuf/proto"
    "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
)

func main() {
    // localhost:9000で待ち受け
    ln, err := net.Listen("tcp", ":9000")
    if err != nil {
        panic(err)
    }
    for {
        conn, err := ln.Accept()
        if err != nil {
            panic(err)
        }
        go func() {
            // 受け取ったデータをbufにcopy
            var buf bytes.Buffer
            io.Copy(&buf, conn)

            // 受け取ったデータをPodSandbox型の変数に格納
            pod := &v1alpha2.PodSandbox{}
            if err := proto.Unmarshal(buf.Bytes(), pod); err != nil {
                panic(err)
            }

            // jsonに変換して標準出力に出力
            versionMarshal := jsonpb.Marshaler{Indent: "  "}
            versionMarshal.Marshal(os.Stdout, pod)
        }()
    }
}

clientから受け取ったデータを分かりやすいようにjsonに変換した上で標準出力に出力しています。

動作確認

事前に作成したserverのプログラムを起動してlocalhost:9000宛に通信ができるようにしておきます。
その上でclientプログラムを起動させると、以下のように表示されてcri-apiで定義されている内容を利用してデータを受け取れている事が確認できます。

{
  "id": "1000",
  "metadata": {
    "name": "FakePod",
    "uid": "123456789",
    "namespace": "System"
  },
  "createdAt": "1"
}

まとめ

cri-apiで定義されている構造体を簡単ではありますが、Goで使ってみる事ができました。
何かの参考になれば幸いです。

6
1
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
6
1