使用Kubernetes的协议缓冲区支持生成的精简的Go客户端。此程序包的行为类似于官方Kubernetes的Go客户端,但只导入两个外部依赖项。
package main import ( "context" "fmt" "log" "github.com/ericchiang/k8s" corev1 "github.com/ericchiang/k8s/apis/core/v1" ) func main() { client, err := k8s.NewInClusterClient() if err != nil { log.Fatal(err) } var nodes corev1.NodeList if err := client.List(context.Background(), "", &nodes); err != nil { log.Fatal(err) } for _, node := range nodes.Items { fmt.Printf("name=%q schedulable=%t\n", *node.Metadata.Name, !*node.Spec.Unschedulable) } }
传递给Create,Update和Delete的对象类型决定了所执行的资源。
Create
Update
Delete
configMap := &corev1.ConfigMap{ Metadata: &metav1.ObjectMeta{ Name: k8s.String("my-configmap"), Namespace: k8s.String("my-namespace"), }, Data: map[string]string{"hello": "world"}, } if err := client.Create(ctx, configMap); err != nil { // handle error } configMap.Data["hello"] = "kubernetes" if err := client.Update(ctx, configMap); err != nil { // handle error } if err := client.Delete(ctx, configMap); err != nil { // handle error }
获取资源需要提供命名空间(对于命名空间对象)和名称。
// Get the "cluster-info" configmap from the "kube-public" namespace var configMap corev1.ConfigMap err := client.Get(ctx, "kube-public", "cluster-info", &configMap)
执行列表操作时,还需要列出或监视的命名空间。
// Pods from the "custom-namespace" var pods corev1.PodList err := client.List(ctx, "custom-namespace", &pods)
特殊值AllNamespaces表示应对所有群集资源执行列表或监视。
AllNamespaces
// Pods in all namespaces var pods corev1.PodList err := client.List(ctx, k8s.AllNamespaces, &pods)
手表需要一个示例类型来确定他们正在观看的资源。 Watch返回一个可用于接收事件流的类型。这些事件包括相同类型的资源和事件的类型(添加,修改,删除)。
Watch
// Watch configmaps in the "kube-system" namespace var configMap corev1.ConfigMap watcher, err := client.Watch(ctx, "kube-system", &configMap) if err != nil { // handle error } defer watcher.Close() for { cm := new(corev1.ConfigMap) eventType, err := watcher.Next(cm) if err != nil { // watcher encountered and error, exit or create a new watcher } fmt.Println(eventType, *cm.Metadata.Name) }
使用主命名空间初始化集群内和集群外客户端。这是列出或观看时使用的建议值。
client, err := k8s.NewInClusterClient() if err != nil { // handle error } // List pods in the namespace the client is running in. var pods corev1.PodList err := client.List(ctx, client.Namespace, &pods)
客户端操作支持用户定义的资源,例如 CustomResourceDefinitions 和聚合API服务器提供的资源。要使用自定义资源,请定义等效的Go结构,然后将其注册到k8s包。默认情况下,客户端在编码和解码自定义资源时将使用JSON序列化。
k8s
import ( "github.com/ericchiang/k8s" metav1 "github.com/ericchiang/k8s/apis/meta/v1" ) type MyResource struct { Metadata *metav1.ObjectMeta `json:"metadata"` Foo string `json:"foo"` Bar int `json:"bar"` } // Required for MyResource to implement k8s.Resource func (m *MyResource) GetMetadata() *metav1.ObjectMeta { return m.Metadata } type MyResourceList struct { Metadata *metav1.ListMeta `json:"metadata"` Items []MyResource `json:"items"` } // Require for MyResourceList to implement k8s.ResourceList func (m *MyResourceList) GetMetadata() *metav1.ListMeta { return m.Metadata } func init() { // Register resources with the k8s package. k8s.Register("resource.example.com", "v1", "myresources", true, &MyResource{}) k8s.RegisterList("resource.example.com", "v1", "myresources", true, &MyResourceList{}) }
注册后,库可以像使用其他任何资源一样使用自定义资源。
func do(ctx context.Context, client *k8s.Client, namespace string) error { r := &MyResource{ Metadata: &metav1.ObjectMeta{ Name: k8s.String("my-custom-resource"), Namespace: &namespace, }, Foo: "hello, world!", Bar: 42, } if err := client.Create(ctx, r); err != nil { return fmt.Errorf("create: %v", err) } r.Bar = -8 if err := client.Update(ctx, r); err != nil { return fmt.Errorf("update: %v", err) } if err := client.Delete(ctx, r); err != nil { return fmt.Errorf("delete: %v", err) } return nil }
如果自定义类型实现 proto.Message ,则客户端在编码和解码类型时将更喜欢protobuf。
proto.Message
可以为任何列表操作提供标签选择器。
l := new(k8s.LabelSelector) l.Eq("tier", "production") l.In("app", "database", "frontend") var pods corev1.PodList err := client.List(ctx, "custom-namespace", &pods, l.Selector())
使用Subresource选项访问子资源。
Subresource
err := client.Update(ctx, &pod, k8s.Subresource("status"))
可以通过手动创建http.Client或解析 Config 对象来构建群集外客户端。以下是从kubeconfig创建客户端的示例:
http.Client
Config
import ( "io/ioutil" "github.com/ericchiang/k8s" "github.com/ghodss/yaml" ) // loadClient parses a kubeconfig from a file and returns a Kubernetes // client. It does not support extensions or client auth providers. func loadClient(kubeconfigPath string) (*k8s.Client, error) { data, err := ioutil.ReadFile(kubeconfigPath) if err != nil { return nil, fmt.Errorf("read kubeconfig: %v", err) } // Unmarshal YAML into a Kubernetes config object. var config k8s.Config if err := yaml.Unmarshal(data, &config); err != nil { return nil, fmt.Errorf("unmarshal kubeconfig: %v", err) } return k8s.NewClient(&config) }
Kubernetes API返回的错误格式为 unversioned.Status 对象,客户端显示为 *k8s.APIError s。需要检查错误代码或故障详细信息的程序可以使用类型转换来访问此信息。
unversioned.Status
*k8s.APIError
// createConfigMap creates a configmap in the client's default namespace // but does not return an error if a configmap of the same name already // exists. func createConfigMap(client *k8s.Client, name string, values map[string]string) error { cm := &v1.ConfigMap{ Metadata: &metav1.ObjectMeta{ Name: &name, Namespace: &client.Namespace, }, Data: values, } err := client.Create(context.TODO(), cm) // If an HTTP error was returned by the API server, it will be of type // *k8s.APIError. This can be used to inspect the status code. if apiErr, ok := err.(*k8s.APIError); ok { // Resource already exists. Carry on. if apiErr.Code == http.StatusConflict { return nil } } return fmt.Errorf("create configmap: %v", err) }