k8sclient: use InClusterConfig() for kubeclient when run as daemonset

When multus is run inside a container, eg as a daemonset, we can use
InClusterConfig() to automatically get the service account token, the
CA certificate, and the apiserver address, all without a kubeconfig
file.
This commit is contained in:
Dan Williams
2018-07-19 09:02:49 -05:00
committed by Kuralamudhan Ramakrishnan
parent 926910af08
commit 42e6894962
3 changed files with 101 additions and 61 deletions

View File

@@ -17,12 +17,14 @@ package k8sclient
import (
"encoding/json"
"fmt"
"os"
"regexp"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"github.com/containernetworking/cni/libcni"
@@ -53,22 +55,6 @@ func (d *defaultKubeClient) GetPod(namespace, name string) (*v1.Pod, error) {
return d.client.Core().Pods(namespace).Get(name, metav1.GetOptions{})
}
func createK8sClient(kubeconfig string) (KubeClient, error) {
// uses the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, fmt.Errorf("createK8sClient: failed to get context for the kubeconfig %v, refer Multus README.md for the usage guide: %v", kubeconfig, err)
}
// creates the clientset
client, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return &defaultKubeClient{client: client}, nil
}
func getPodNetworkAnnotation(client KubeClient, k8sArgs types.K8sArgs) (string, string, error) {
var err error
@@ -276,7 +262,44 @@ type KubeClient interface {
GetPod(namespace, name string) (*v1.Pod, error)
}
func GetK8sNetwork(args *skel.CmdArgs, kubeconfig string, k8sclient KubeClient, confdir string) ([]*types.DelegateNetConf, error) {
func GetK8sClient(kubeconfig string, kubeClient KubeClient) (KubeClient, error) {
// If we get a valid kubeClient (eg from testcases) just return that
// one.
if kubeClient != nil {
return kubeClient, nil
}
var err error
var config *rest.Config
// Otherwise try to create a kubeClient from a given kubeConfig
if kubeconfig != "" {
// uses the current context in kubeconfig
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, fmt.Errorf("GetK8sClient: failed to get context for the kubeconfig %v, refer Multus README.md for the usage guide: %v", kubeconfig, err)
}
} else if os.Getenv("KUBERNETES_SERVICE_HOST") != "" && os.Getenv("KUBERNETES_SERVICE_PORT") != "" {
// Try in-cluster config where multus might be running in a kubernetes pod
config, err = rest.InClusterConfig()
if err != nil {
return nil, fmt.Errorf("createK8sClient: failed to get context for in-cluster kube config, refer Multus README.md for the usage guide: %v", err)
}
} else {
// No kubernetes config; assume we shouldn't talk to Kube at all
return nil, nil
}
// creates the clientset
client, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return &defaultKubeClient{client: client}, nil
}
func GetK8sNetwork(k8sclient KubeClient, args *skel.CmdArgs, confdir string) ([]*types.DelegateNetConf, error) {
k8sArgs := types.K8sArgs{}
err := cnitypes.LoadArgs(args.Args, &k8sArgs)
@@ -284,13 +307,6 @@ func GetK8sNetwork(args *skel.CmdArgs, kubeconfig string, k8sclient KubeClient,
return nil, err
}
if k8sclient == nil {
k8sclient, err = createK8sClient(kubeconfig)
if err != nil {
return nil, err
}
}
netAnnot, defaultNamespace, err := getPodNetworkAnnotation(k8sclient, k8sArgs)
if err != nil {
return nil, err

View File

@@ -77,7 +77,9 @@ var _ = Describe("k8sclient operations", func() {
// net3 is not used; make sure it's not accessed
fKubeClient.AddNetConfig(fakePod.ObjectMeta.Namespace, "net3", net3)
delegates, err := GetK8sNetwork(args, "", fKubeClient, tmpDir)
kubeClient, err := GetK8sClient("", fKubeClient)
Expect(err).NotTo(HaveOccurred())
delegates, err := GetK8sNetwork(kubeClient, args, tmpDir)
Expect(err).NotTo(HaveOccurred())
Expect(fKubeClient.PodCount).To(Equal(1))
Expect(fKubeClient.NetCount).To(Equal(2))
@@ -106,7 +108,9 @@ var _ = Describe("k8sclient operations", func() {
fKubeClient.AddPod(fakePod)
fKubeClient.AddNetConfig(fakePod.ObjectMeta.Namespace, "net3", net3)
delegates, err := GetK8sNetwork(args, "", fKubeClient, tmpDir)
kubeClient, err := GetK8sClient("", fKubeClient)
Expect(err).NotTo(HaveOccurred())
delegates, err := GetK8sNetwork(kubeClient, args, tmpDir)
Expect(len(delegates)).To(Equal(0))
Expect(err).To(MatchError("GetK8sNetwork: failed getting the delegate: getKubernetesDelegate: failed to get network resource, refer Multus README.md for the usage guide: resource not found"))
})
@@ -146,7 +150,9 @@ var _ = Describe("k8sclient operations", func() {
"cniVersion": "0.2.0"
}`)
delegates, err := GetK8sNetwork(args, "", fKubeClient, tmpDir)
kubeClient, err := GetK8sClient("", fKubeClient)
Expect(err).NotTo(HaveOccurred())
delegates, err := GetK8sNetwork(kubeClient, args, tmpDir)
Expect(err).NotTo(HaveOccurred())
Expect(fKubeClient.PodCount).To(Equal(1))
Expect(fKubeClient.NetCount).To(Equal(3))
@@ -169,7 +175,9 @@ var _ = Describe("k8sclient operations", func() {
fKubeClient := testutils.NewFakeKubeClient()
fKubeClient.AddPod(fakePod)
delegates, err := GetK8sNetwork(args, "", fKubeClient, tmpDir)
kubeClient, err := GetK8sClient("", fKubeClient)
Expect(err).NotTo(HaveOccurred())
delegates, err := GetK8sNetwork(kubeClient, args, tmpDir)
Expect(len(delegates)).To(Equal(0))
Expect(err).To(MatchError("parsePodNetworkAnnotation: failed to parse pod Network Attachment Selection Annotation JSON format: invalid character 'a' looking for beginning of value"))
})
@@ -195,7 +203,9 @@ var _ = Describe("k8sclient operations", func() {
"cniVersion": "0.2.0"
}`)
delegates, err := GetK8sNetwork(args, "", fKubeClient, tmpDir)
kubeClient, err := GetK8sClient("", fKubeClient)
Expect(err).NotTo(HaveOccurred())
delegates, err := GetK8sNetwork(kubeClient, args, tmpDir)
Expect(err).NotTo(HaveOccurred())
Expect(fKubeClient.PodCount).To(Equal(1))
Expect(fKubeClient.NetCount).To(Equal(2))
@@ -244,7 +254,9 @@ var _ = Describe("k8sclient operations", func() {
net2Name := filepath.Join(tmpDir, "20-net2.conf")
fKubeClient.AddNetFile(fakePod.ObjectMeta.Namespace, "net2", net2Name, "asdfasdfasfdasfd")
delegates, err := GetK8sNetwork(args, "", fKubeClient, tmpDir)
kubeClient, err := GetK8sClient("", fKubeClient)
Expect(err).NotTo(HaveOccurred())
delegates, err := GetK8sNetwork(kubeClient, args, tmpDir)
Expect(len(delegates)).To(Equal(0))
Expect(err).To(MatchError(fmt.Sprintf("GetK8sNetwork: failed getting the delegate: cniConfigFromNetworkResource: err in getCNIConfigFromFile: Error loading CNI config file %s: error parsing configuration: invalid character 'a' looking for beginning of value", net2Name)))
})