これは、このセクションの複数ページの印刷可能なビューです。 印刷するには、ここをクリックしてください.

このページの通常のビューに戻る.

Getting Started

Kuestaを動かしてみよう

    このチュートリアルでは、以下のステップでKuestaを構築し、動作確認を行います。

    1. ローカルのKubernetesクラスターを作成する
    2. Kuestaをインストールする
    3. 装置エミュレータを立ち上げる
    4. 新しいServiceコンフィグを作成して、GitOpsを介して装置エミュレータに設定を投入する

    事前準備

    1. golang (v1.20.4+)) をインストールしてください。カスタムコントローラーのツール類を使用するために必要です。
    2. docker (v20.10.24+) をインストールしてください。kindの実行に必要です。
    3. kind (v0.12.0+) をインストールしてください。ローカルのKubernetesクラスタの構築に使用します。
    4. kubectl (v1.25.4+) をインストールしてください。Kubernetesクラスタに対してコマンドを実行する際に使用します。
    5. cue (v0.4.x) をインストールしてください。Kuestaのインストールスクリプトの実行に必要です。
    6. gnmic (v0.26.0+) をインストールしてください。Kuestaサーバに対してgNMIリクエストを行うために必要です。

    ローカルKubernetesクラスタの立ち上げ

    以下のコマンドを実行して、ローカルのKubernetesクラスタを立ち上げます。

    kind create cluster
    

    実行が完了したら、以下のコマンドを実行して、Kubernetesクラスタが正常に作成されたことを確認します。

    kubectl cluster-info
    

    以下のような出力が表示されたら、ローカルクラスタは正常に動作しています。

    Kubernetes control plane is running at https://127.0.0.1:52096
    CoreDNS is running at https://127.0.0.1:52096/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    

    検証用のGithubレポジトリの作成

    KuestaのGitOpsを用いてネットワーク装置に設定を行うには、2つのGitHubレポジトリを作成する必要があります。 1つ目はGitOpsの起点となるコンフィグ管理レポジトリで、2つ目はネットワーク装置の実際のコンフィグの変更履歴を管理するレポジトリです。 Kuesta Example レポジトリをテンプレートとして使用することで、これらのレポジトリを簡単に作成できます。 レポジトリ名は、小文字の英数字、’-‘または’.‘で構成され、英数字で始まり、英数字で終わる必要があります。

    以下を2回実行して、2つのGitHubレポジトリを作成してください。

    1. Kuesta Example レポジトリの Use this template ボタンをクリックしてください。

    2. レポジトリ名を入力して、 Create repository from template ボタンをクリックしてください。レポジトリの公開・非公開については、好きな方を選択してください。

    Kuestaと検証用サンプルリソースのインストール

    Kuestaと、検証用のドライバオペレータや装置エミュレータなどのサンプルリソースをインストールするには、以下のコマンドを実行してください。

    git clone https://github.com/nttcom/kuesta.git
    cd kuesta/tool/install
    cue install
    

    プロンプトが表示されますので、指示に従ってパラメータを入力してください。 GitHub repository for config GitHub repository for statusは前項で作成した2つの検証用のGithubレポジトリをそれぞれ指定してください。

    GitHub repository for config: https://github.com/<your_org>/<your_config_repo>
    GitHub repository for status: https://github.com/<your_org>/<your_status_repo>
    GitHub username: <your_username>
    GitHub private access token: <your_private_access_token>
    Are these git repositories private? (yes|no): no
    Do you need sample driver and emulator for trial?: (yes|no) yes
    
    ---
    GitHub Config Repository: https://github.com/<your_org>/<your_config_repo>
    GitHub Status Repository: https://github.com/<your_org>/<your_status_repo>
    GitHub Username: <your_username>
    GitHub Access Token: ***
    Use Private Repo: true
    
    Image Registry: ghcr.io/nttcom/kuesta
    Version: latest
    Deploy sample driver and emulator: true
    ---
    
    Continue? (yes|no) yes
    

    KuestaはGitへのプッシュやプルリクエストの作成を行うため、GitHubの personal access token (PAT) が必要です(classic推奨)。 ここで入力されたPATは、ローカルのKubernetesクラスタ内のSecretリソースにのみ保存されます。ローカルのKubernetesクラスタを削除することで、どこにもデータを残さずに完全に削除できます。

    インストールスクリプトの実行が完了したら、 kubectl コマンドを実行することで何がインストールされたかを確認できます。

    1: Custom Resource Definitions(CRDs):

    kubectl get customresourcedefinitions.apiextensions.k8s.io
    
    NAME                                        CREATED AT
    buckets.source.toolkit.fluxcd.io            2023-01-10T06:31:20Z
    certificaterequests.cert-manager.io         2023-01-10T06:31:19Z
    certificates.cert-manager.io                2023-01-10T06:31:19Z
    challenges.acme.cert-manager.io             2023-01-10T06:31:19Z
    clusterissuers.cert-manager.io              2023-01-10T06:31:19Z
    devicerollouts.kuesta.hrk091.dev            2023-01-10T06:43:30Z
    gitrepositories.source.toolkit.fluxcd.io    2023-01-10T06:31:20Z
    helmcharts.source.toolkit.fluxcd.io         2023-01-10T06:31:20Z
    helmrepositories.source.toolkit.fluxcd.io   2023-01-10T06:31:20Z
    issuers.cert-manager.io                     2023-01-10T06:31:19Z
    ocdemoes.kuesta.hrk091.dev                  2023-01-10T06:43:36Z
    ocirepositories.source.toolkit.fluxcd.io    2023-01-10T06:31:20Z
    orders.acme.cert-manager.io                 2023-01-10T06:31:19Z
    

    kuesta.hrk091.devsource.toolkit.fluxcd.iocert-manager.io に属するCRDが追加されていることが確認できます。

    2: Pods:

    kubectl get pods -A | grep -v 'kube-system'
    
    NAMESPACE                NAME                                                  READY   STATUS    RESTARTS   AGE
    cert-manager             cert-manager-7475574-t7qlm                            1/1     Running   0          12m
    cert-manager             cert-manager-cainjector-d5dc6cd7f-wbh6r               1/1     Running   0          12m
    cert-manager             cert-manager-webhook-6868bd8b7-kc85s                  1/1     Running   0          12m
    device-operator-system   device-operator-controller-manager-5d8648469b-57x4l   2/2     Running   0          11s
    flux-system              source-controller-7ff779586b-wsgf7                    1/1     Running   0          12m
    kuesta-getting-started   gnmi-fake-oc01-79d4d679b4-tvm78                       1/1     Running   0          10s
    kuesta-getting-started   gnmi-fake-oc02-69d9cc664d-56bsz                       1/1     Running   0          10s
    kuesta-getting-started   subscriber-oc01                                       1/1     Running   0          9s
    kuesta-getting-started   subscriber-oc02                                       1/1     Running   0          9s
    kuesta-system            kuesta-aggregator-7586999c47-jj7m4                    1/1     Running   0          27s
    kuesta-system            kuesta-server-85fc4f8646-kq72c                        1/1     Running   0          27s
    local-path-storage       local-path-provisioner-9cd9bd544-lk9w9                1/1     Running   0          16m
    provisioner-system       provisioner-controller-manager-7675d487c8-w6f7x       1/2     Running   0          17s
    

    全てのPodがRunningのステータスになっていたら、準備完了です。

    以下の各namespaceに、Kuestaのコア機能として必要なサービスがデプロイされています。

    • kuesta-system
      • Kuestaのコア機能やAPIを提供するサーバ
    • provisioner-system
      • KuestaのKubernetesカスタムオペレータ。GitOpsやトランザクション管理に使用
    • flux-system
      • FluxCDのカスタムコントローラ
    • cert-manager
      • プライベートCAの認証局、およびmTLS用の証明書発行

    また、以下のnamespaceには、本チュートリアル用のリソースがデプロイされています。

    • device-operator-system
      • チュートリアルで使用する装置エミュレータに対し設定投入を行うためのドライバとして振る舞うKubernetesカスタムオペレータ
    • kuesta-getting-started
      • チュートリアルで使用する装置エミュレータやエミュレータに設定を行うためのKubernetesカスタムリソースなど

    以下の2つは、OpenConfig over gNMIで設定が可能な装置エミュレータです。本チュートリアルでは、 oc01oc02 の2つのエミュレータがデプロイされています。

    kuesta-getting-started   gnmi-fake-oc01-79d4d679b4-tvm78                       1/1     Running   0          10s
    kuesta-getting-started   gnmi-fake-oc02-69d9cc664d-56bsz                       1/1     Running   0          10s
    

    ポートフォワーディングして gnmic からリクエストを行うことで設定されているコンフィグを確認できますので、必要に応じて実施してください。 以下のコマンドで、装置エミュレータ内のコンフィグの確認ができます。

    # oc01のコンフィグを取得
    kubectl -n kuesta-getting-started port-forward svc/gnmi-fake-oc01 9339:9339
    gnmic -a :9339 -u admin -p admin get --path "" --encoding JSON --skip-verify
    

    Serviceコンフィグを作成し、GitOpsを走らせる

    Service は、ネットワークコンフィグを高レベルに抽象化したモデルです。Serviceを作成/変更することで、関連する複数のネットワーク装置にまとめて設定を投入することができます。

    本チュートリアル用のサンプルレポジトリの中には、 oc-circuit という名のServiceが設定されていますので、これを用いて動作確認を行います。 ServiceはCUEで記述されます。例として、 oc-circuit Serviceの定義を以下に示します。

    package oc_circuit
    
    import (
    	ocdemo "github.com/hrk091/kuesta-testdata/pkg/ocdemo"
    )
    
    #Input: {
    	// kuesta:"key=1"
    	vlanID: uint32
    	endpoints: [...{
    		device: string
    		port:   uint32
    	}]
    }
    
    #Template: {
    	input: #Input
    
    	output: devices: {
    		for _, ep in input.endpoints {
    			"\(ep.device)": config: {
    				ocdemo.#Device
    
    				let _portName = "Ethernet\(ep.port)"
    				Interface: "\(_portName)": SubInterface: "\(input.vlanID)": {
    					Ifindex:     ep.port
    					Index:       input.vlanID
    					Name:        "\(_portName).\(input.vlanID)"
    					AdminStatus: 1
    					OperStatus:  1
    				}
    
    				Vlan: "\(input.vlanID)": {
    					VlanId: input.vlanID
    					Name:   "VLAN\(input.vlanID)"
    					Status: ocdemo.#Vlan_Status_ACTIVE
    					Tpid:   ocdemo.#OpenconfigVlanTypes_TPID_TYPES_UNSET
    				}
    			}
    		}
    	}
    }
    

    oc-circuit Serviceは、#Template フィールドに定義された内容に従い、受け取った #Template.input(Serviceコンフィグ)を #Template.output (複数のネットワーク装置のコンフィグ)に変換します。 #Input の定義されているServiceのインターフェーススキーマを見ると、oc-circuit Serviceを使用するためには、 VLAN ID と複数のネットワーク装置のポートが必要なことがわかります。 これらを指定して oc-circuit Serviceを作成すると、 #Template のマッピング定義に従い、VLAN定義と指定したポートのVLANサブインターフェースが作成されます。

    以下の手順にしたがって、oc-circuit Serviceを作成してください。

    1: oc-circuit Serviceの作成をリクエストするために、以下のJSONファイルを oc-circuit-vlan100.json という名前で保存してください。 このServiceでは、oc01とoc02の両エミュレータに対して、ポート番号1のインターフェイスにVLAN ID=100のVLANサブインターフェースを作成することをリクエストしています。

    {
        "vlanID": 100,
        "endpoints": [
            {
                "device": "oc01",
                "port": 1
            },
            {
                "device": "oc02",
                "port": 1
            }
        ]
    }
    

    httpインターフェースを利用する場合、上に代わって以下JSONを作成してください。(pathにはServiceのパス、valueには投入するServiceの値を指定)

    {
        "path": "/services/oc_circuit/100",
        "value": {
            "vlanID": 100,
            "endpoints": [
                {
                    "device": "oc01",
                    "port": 1
                },
                {
                    "device": "oc02",
                    "port": 1
                }
            ]
        }
    }
    

    2: ローカルのKubernetesクラスタで動作しているKuestaサーバのPodに対してポートフォワーディングしてください。

    kubectl -n kuesta-system port-forward svc/kuesta-server 9339:9339
    

    httpインターフェースを利用する場合は以下です。

    kubectl -n kuesta-system port-forward svc/kuesta-server 8080:8080
    

    3: gnmicを用いて、Kuestaサーバに対してgNMI SetRequestを送ってください。

    gnmic -a :9339 -u dummy -p dummy set --replace-path "/services/service[kind=oc_circuit][vlanID=100]" --encoding JSON --insecure --replace-file oc-circuit-vlan100.json
    

    httpインターフェースを利用する場合は、curlを用いてKuestaサーバに対して以下POST Requestを送ってください。

    curl -X POST -H "Content-Type: application/json" -d @oc-circuit-vlan100.json http://localhost:8080/set
    

    4: GitHubのWebコンソールを用いて、本チュートリアル向けに作成したコンフィグ用のGitHubレポジトリのプルリクエスト(PullRequest: PR)を確認してください。 PR一覧 にアクセスすると、 [kuesta] Automated PR というタイトルのPRが確認できます。 PRのコメントを見ると、どのServiceとどのネットワーク装置が変更されたのかがわかりますし、 Files changed タブを確認すると詳細な変更点が確認できます。

    5: PRブランチをマージする前に、ローカルのKubernetesクラスターで DeviceRollout リソースをモニターしてください。 DeviceRollout リソースは、Gitレポジトリからプルしたコンフィグを各ネットワーク装置に設定する際の状態管理を行っています。以下のコマンドを実行してください。

    kubectl -n kuesta-getting-started get devicerollouts.kuesta.hrk091.dev -w
    

    DeviceRollout リソースが一つ表示され、その STATUSCompleted になっていれば、GitOpsによるデリバリプロセスを流す準備は完了です。

    NAME              PHASE     STATUS
    kuesta-testdata   Healthy   Completed
    

    6: GitHubのWebコンソール上で、PRをマージしてください。その後、 DeviceRollout をモニターしているターミナル画面に移動してください。 1分以内に、 DeviceRolloutSTATUSRunning に変わり、その後 Completed に変わることを確認してください。

    NAME              PHASE     STATUS
    kuesta-testdata   Healthy   Completed
    kuesta-testdata   Healthy   Completed
    kuesta-testdata   Healthy   Running
    kuesta-testdata   Healthy   Running
    kuesta-testdata   Healthy   Running
    kuesta-testdata   Healthy   Completed
    

    7: 装置コンフィグが本当に更新されたのかを確認します。 gnmic を用いて、gNMI GetRequestをKuestaサーバに対して送り、装置コンフィグ全体を取得してください。

    gnmic -a :9339 -u admin -p admin get --path "/devices/device[name=oc01]" --path "/devices/device[name=oc02]" --encoding JSON --insecure
    

    httpインターフェースを利用する場合は、curlを用いてKuestaサーバに対して以下POST Requestを送ってください。

    curl -X POST -H "Content-Type: application/json" -d '{"paths": ["/devices/oc01", "/devices/oc02"]}'  http://localhost:8080/get
    

    以下のようなレスポンスが表示されます。

    [
      {
        "source": ":9339",
        "timestamp": 1673360105000000000,
        "time": "2023-01-10T23:15:05+09:00",
        "updates": [
          {
            "Path": "devices/device[name=oc01]",
            "values": {
              "devices/device": {
                "Interface": {
                  "Ethernet1": {
                    "AdminStatus": 1,
                    "Description": "awesome interface!!",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet1",
                    "OperStatus": 1,
                    "Subinterface": {
                      "100": {
                        "AdminStatus": 1,
                        "Ifindex": 1,
                        "Index": 100,
                        "Name": "Ethernet1.100",
                        "OperStatus": 1
                      },
                      ...
                    },
                    ...
                  },
                  ...
                },
                "Vlan": {
                  "100": {
                    "Member": [],
                    "Name": "VLAN100",
                    "Status": 1,
                    "Tpid": 0,
                    "VlanId": 100
                  },
                  ...
    

    httpインターフェースを使用した場合のレスポンスは以下です。

    [
        {
            "Interface": {
                "Ethernet1": {
                    "AdminStatus": 1,
                    "Description": "",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet1",
                    "OperStatus": 1,
                    "SubInterface": {
                        "100": {
                            "AdminStatus": 1,
                            "Ifindex": 1,
                            "Index": 100,
                            "Name": "Ethernet1.100",
                            "OperStatus": 1
                        }
                    },
                    "Subinterface": {},
                    "Type": 80
                },
                "Ethernet2": {
                    "AdminStatus": 1,
                    "Description": "",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet2",
                    "OperStatus": 1,
                    "Subinterface": {},
                    "Type": 80
                },
                "Ethernet3": {
                    "AdminStatus": 1,
                    "Description": "",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet3",
                    "OperStatus": 1,
                    "Subinterface": {},
                    "Type": 80
                }
            },
            "Vlan": {
                "100": {
                    "Member": [],
                    "Name": "VLAN100",
                    "Status": 1,
                    "Tpid": 0,
                    "VlanId": 100
                }
            }
        },
        {
            "Interface": {
                "Ethernet1": {
                    "AdminStatus": 1,
                    "Description": "",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet1",
                    "OperStatus": 1,
                    "SubInterface": {
                        "100": {
                            "AdminStatus": 1,
                            "Ifindex": 1,
                            "Index": 100,
                            "Name": "Ethernet1.100",
                            "OperStatus": 1
                        }
                    },
                    "Subinterface": {},
                    "Type": 80
                },
                "Ethernet2": {
                    "AdminStatus": 1,
                    "Description": "",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet2",
                    "OperStatus": 1,
                    "Subinterface": {},
                    "Type": 80
                },
                "Ethernet3": {
                    "AdminStatus": 1,
                    "Description": "",
                    "Enabled": false,
                    "Mtu": 9000,
                    "Name": "Ethernet3",
                    "OperStatus": 1,
                    "Subinterface": {},
                    "Type": 80
                }
            },
            "Vlan": {
                "100": {
                    "Member": [],
                    "Name": "VLAN100",
                    "Status": 1,
                    "Tpid": 0,
                    "VlanId": 100
                }
            }
        }
    ]
    

    レスポンスを確認すると、oc01とoc02の両方の装置エミュレータに対して、VLAN ID=100のVLAN定義とVLANサブインターフェースが設定されていることが分かります。 また、これらの装置コンフィグの変更内容はチュートリアル向けに作成したステータス用のGitレポジトリに対してコミット・プッシュされています。ステータス用のGitレポジトリのメインブランチのHEADを見ると、変更が保存されていることが確認できます。

    ローカルKubernetesクラスタの削除

    このチュートリアルで作成したローカルのKubernetesクラスタを削除するには、以下のコマンドを実行してください。

    kind delete cluster
    

    プライベートレポジトリのアクセス用に作成したPATは、不要であれば忘れずに削除しましょう。