私は https://github.com/kubernetes/client-go を使用していますが、すべてうまくいきます。
公式のKubernetesダッシュボードのマニフェスト(YAML)があります: https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta4/aio/deploy/recommended.yaml
Client-goを使用して、Goコードでこのマニフェストのkubectl apply
を模倣したいと思います。
YAMLバイトをいくつかの(アン)マーシャリングして、パッケージで定義されている正しいAPIタイプに変換する必要があることを理解しています: https://github.com/kubernetes/api
クラスターに単一のAPIタイプを正常にCreate
edしましたが、同じではないタイプのリストを含むマニフェストに対してこれを行う方法?これらのさまざまなタイプをサポートするリソースkind: List*
はありますか?
現在の回避策は、csplit
を区切り文字として---を使用してYAMLファイルを分割することです
csplit /path/to/recommended.yaml /---/ '{*}' --prefix='dashboard.' --suffix-format='%03d.yaml'
次に、作成した新しい(14)パーツをループし、それらのバイトを読み取り、UniversalDeserializerのデコーダーによって返されたオブジェクトのタイプを切り替え、k8sクライアントセットを使用して正しいAPIメソッドを呼び出します。
これをプログラムで実行して、ダッシュボードの新しいバージョンをクラスターに更新します。また、Metrics Serverや他の多くのリソースに対してもこれを行う必要があります。代替の(おそらくより簡単な)方法は、kubectlをコンテナーイメージにインストールしてコードを出荷し、kubectl apply -f -
を直接呼び出すことです。しかし、それは、kubectlがそれを使用できるように、kube構成をディスクに書き込むか、インラインで渡す必要があることも意味します。
私はこの問題が役立つことがわかりました: https://github.com/kubernetes/client-go/issues/19 デコーダーはここにあります: https://github.com/kubernetes/apimachinery/tree/master/pkg/runtime/serializer
ここでclient-goに公開されています: https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go#L69
Kubectlで使用されるRunConvertメソッドも確認しました: https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/convert/convert.go#L139 そして、私は自分の genericclioptions.IOStreams を提供して出力を取得できると仮定しますか?
[client-go]とタグ付けされた他の質問も調べましたが、ほとんどは古い例を使用するか、単一のkind
が定義されたYAMLファイルを使用し、APIはその後変更されました。
編集:複数のクラスターに対してこれを行う必要があり、プログラムでクラスターを作成しているため(AWS EKS API + CloudFormation/ eksctl )、ServiceAccount
sを作成するオーバーヘッドを最小限にしたいと思います多くのクラスターコンテキスト間、多くのAWSアカウント間。理想的には、クライアントセットの作成に関連する唯一の認証手順は aws-iam-authenticator を使用して、クラスターデータ(名前、地域、CA証明書など)を使用してトークンを取得することです。 aws-iam-authenticatorはしばらくリリースされていませんが、master
の内容により、サードパーティの役割のクロスアカウントの役割と外部IDを渡すことができます。 IMO、これはServiceAccount
(および [〜#〜] irsa [〜#〜] )を使用するよりもクリーンです。これは、他のAWSサービスアプリケーション(バックエンドAPIを作成し、対話する必要があるアドオンをこれらのクラスターに適用します。
編集:私は最近 https://github.com/ericchiang/k8s を見つけました。大まかに言うと、client-goよりも使い方が明らかに簡単ですが、この動作はサポートされていません。
YAMLファイルをKubernetesにデシリアライズする方法を理解したようですruntime.Object
s、しかし問題は動的にruntime.Object
種類ごとに特別なコードを記述する必要はありません。
kubectl
は REST API と直接やり取りすることでこれを実現します。具体的には、 resource.Helper を使用します。
私のコードには、次のようなものがあります:
import (
meta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
"k8s.io/apimachinery/pkg/runtime"
)
func createObject(kubeClientset kubernetes.Interface, restConfig rest.Config, obj runtime.Object) error {
// Create a REST mapper that tracks information about the available resources in the cluster.
groupResources, err := restmapper.GetAPIGroupResources(kubeClientset.Discovery())
if err != nil {
return err
}
rm := restmapper.NewDiscoveryRESTMapper(groupResources)
// Get some metadata needed to make the REST request.
gvk := obj.GetObjectKind().GroupVersionKind()
gk := schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}
mapping, err := rm.RESTMapping(gk, gvk.Version)
if err != nil {
return err
}
name, err := meta.NewAccessor().Name(obj)
if err != nil {
return err
}
// Create a client specifically for creating the object.
restClient, err := newRestClient(restConfig, mapping.GroupVersionKind.GroupVersion())
if err != nil {
return err
}
// Use the REST helper to create the object in the "default" namespace.
restHelper := resource.NewHelper(restClient, mapping)
return restHelper.Create("default", false, obj, &metav1.CreateOptions{})
}
func newRestClient(restConfig rest.Config, gv schema.GroupVersion) (rest.Interface, error) {
restConfig.ContentConfig = resource.UnstructuredPlusDefaultContentConfig()
restConfig.GroupVersion = &gv
if len(gv.Group) == 0 {
restConfig.APIPath = "/api"
} else {
restConfig.APIPath = "/apis"
}
return rest.RESTClientFor(&restConfig)
}