Managing secrets in a Kubernetes environment using the k8s.io/client-go library is crucial for maintaining secure access to sensitive information such as passwords, OAuth tokens, and ssh keys. This documentation provides a step-by-step guide on how to store and manage secrets using client-go, specifically focusing on production use cases.

1. Creating a Secret

Creating a secret in Kubernetes can be accomplished using the Secret type from the k8s.io/api/core/v1 package. Below is an example on how to create a secret programmatically.

package main

import (
    "context"
    "fmt"
    "os"

    v1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    kubeconfig := os.Getenv("KUBECONFIG")
    
    // Build the clientset
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        panic(err.Error())
    }
    
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }
    
    // Create a secret
    secret := &v1.Secret{
        ObjectMeta: metav1.ObjectMeta{
            Name: "my-secret",
        },
        Type: v1.SecretTypeOpaque,
        Data: map[string][]byte{
            "password": []byte("secret-password"),
        },
    }
    
    // Use the clientset to create the secret in the "default" namespace
    secretsClient := clientset.CoreV1().Secrets("default")
    result, err := secretsClient.Create(context.TODO(), secret, metav1.CreateOptions{})
    if err != nil {
        panic(err.Error())
    }
    
    fmt.Printf("Created secret %q.\n", result.GetObjectMeta().GetName())
}

2. Retrieving a Secret

To access a secret, you would typically read it from the Kubernetes API using the client-go library. Here’s how to retrieve a secret:

func getSecret(clientset *kubernetes.Clientset, name string) (*v1.Secret, error) {
    secret, err := clientset.CoreV1().Secrets("default").Get(context.TODO(), name, metav1.GetOptions{})
    if err != nil {
        return nil, err
    }
    return secret, nil
}

// Usage
secret, err := getSecret(clientset, "my-secret")
if err != nil {
    panic(err)
}
fmt.Printf("Retrieved secret: %s\n", secret.Data["password"])

3. Updating a Secret

Updating an existing secret can also be done using the client-go library. You can retrieve the secret, modify it, and then apply the changes.

func updateSecret(clientset *kubernetes.Clientset, name string, newData string) (*v1.Secret, error) {
    secret, err := getSecret(clientset, name)
    if err != nil {
        return nil, err
    }
    
    // Update the secret's data
    secret.Data["password"] = []byte(newData)

    updatedSecret, err := clientset.CoreV1().Secrets("default").Update(context.TODO(), secret, metav1.UpdateOptions{})
    if err != nil {
        return nil, err
    }
    return updatedSecret, nil
}

// Usage
updatedSecret, err := updateSecret(clientset, "my-secret", "new-secret-password")
if err != nil {
    panic(err)
}
fmt.Printf("Updated secret: %s\n", updatedSecret.Data["password"])

4. Deleting a Secret

If you need to delete a secret, you can use the Delete method:

func deleteSecret(clientset *kubernetes.Clientset, name string) error {
    return clientset.CoreV1().Secrets("default").Delete(context.TODO(), name, metav1.DeleteOptions{})
}

// Usage
if err := deleteSecret(clientset, "my-secret"); err != nil {
    panic(err)
}
fmt.Println("Secret deleted.")

5. Using Secrets in Pod Spec

In production environments, secrets should be used in pod specifications to ensure that applications can access sensitive data securely. Here’s how you can reference a secret in a pod specification:

pod := &v1.Pod{
    ObjectMeta: metav1.ObjectMeta{
        Name: "my-app",
    },
    Spec: v1.PodSpec{
        Containers: []v1.Container{
            {
                Name:  "app-container",
                Image: "myapp:latest",
                Env: []v1.EnvVar{
                    {
                        Name: "PASSWORD",
                        ValueFrom: &v1.EnvVarSource{
                            SecretKeyRef: &v1.SecretKeySelector{
                                Name: "my-secret",
                                Key:  "password",
                            },
                        },
                    },
                },
            },
        },
    },
}

Conclusion

This documentation provides a structured approach to managing secrets in a Kubernetes environment using the k8s.io/client-go library. With the methods demonstrated, developers can effectively create, retrieve, update, and delete secrets, as well as use them in their applications securely.

Source: client-go