kubelet之DockerClient源码分析

DockerClient 是KubeletDeps结构体的成员变量

type KubeletDeps struct {
    // TODO(mtaufen): KubeletBuilder:
    //                Mesos currently uses this as a hook to let them make their own call to
    //                let them wrap the KubeletBootstrap that CreateAndInitKubelet returns with
    //                their own KubeletBootstrap. It's a useful hook. I need to think about what
    //                a nice home for it would be. There seems to be a trend, between this and
    //                the Options fields below, of providing hooks where you can add extra functionality
    //                to the Kubelet for your solution. Maybe we should centralize these sorts of things?
    Builder KubeletBuilder

    // TODO(mtaufen): ContainerRuntimeOptions and Options:
    //                Arrays of functions that can do arbitrary things to the Kubelet and the Runtime
    //                seem like a difficult path to trace when it's time to debug something.
    //                I'm leaving these fields here for now, but there is likely an easier-to-follow
    //                way to support their intended use cases. E.g. ContainerRuntimeOptions
    //                is used by Mesos to set an environment variable in containers which has
    //                some connection to their container GC. It seems that Mesos intends to use
    //                Options to add additional node conditions that are updated as part of the
    //                Kubelet lifecycle (see https://github.com/kubernetes/kubernetes/pull/21521).
    //                We should think about providing more explicit ways of doing these things.
    ContainerRuntimeOptions []kubecontainer.Option
    Options                 []Option

    // Injected Dependencies
    Auth              server.AuthInterface
    CAdvisorInterface cadvisor.Interface
    Cloud             cloudprovider.Interface
    ContainerManager  cm.ContainerManager


DockerClient dockertools.DockerInterface

    EventClient       *clientset.Clientset
    KubeClient        *clientset.Clientset
    Mounter           mount.Interface
    NetworkPlugins    []network.NetworkPlugin
    OOMAdjuster       *oom.OOMAdjuster
    OSInterface       kubecontainer.OSInterface
    PodConfig         *config.PodConfig
    Recorder          record.EventRecorder
    Writer            kubeio.Writer
    VolumePlugins     []volume.VolumePlugin
    TLSOptions        *server.TLSOptions
}

而构建dockerClient 所需要的DockerEndpoint参数是KubeletConfiguration的成员变量

type KubeletConfiguration struct {
DockerEndpoint string `json:"dockerEndpoint"`
}

而KubeletConfiguration 是KubeletServer成员变量

type KubeletServer struct {
    componentconfig.KubeletConfiguration

    KubeConfig          flag.StringFlag
    BootstrapKubeconfig string

    // If true, an invalid KubeConfig will result in the Kubelet exiting with an error.
    RequireKubeConfig bool
    AuthPath          flag.StringFlag // Deprecated -- use KubeConfig instead
    APIServerList     []string        // Deprecated -- use KubeConfig instead

    // Insert a probability of random errors during calls to the master.
    ChaosChance float64
    // Crash immediately, rather than eating panics.
    ReallyCrashForTesting bool

    // TODO(mtaufen): It is increasingly looking like nobody actually uses the
    //                Kubelet's runonce mode anymore, so it may be a candidate
    //                for deprecation and removal.
    // If runOnce is true, the Kubelet will check the API server once for pods,
    // run those in addition to the pods specified by the local manifest, and exit.
    RunOnce bool
}

实际上如果没有指定该参数的话,会默认使用端点”unix:///var/run/docker.sock”做为DockerEndpoint。可以查看NewEnvClient()接口。
具体初始化dockerClient的具体代码

func UnsecuredKubeletDeps(s *options.KubeletServer) (*kubelet.KubeletDeps, error) {

    // Initialize the TLS Options
    tlsOptions, err := InitializeTLS(&s.KubeletConfiguration)
    if err != nil {
        return nil, err
    }

    mounter := mount.New(s.ExperimentalMounterPath)
    var writer kubeio.Writer = &kubeio.StdWriter{}
    if s.Containerized {
        glog.V(2).Info("Running kubelet in containerized mode (experimental)")
        mounter = mount.NewNsenterMounter()
        writer = &kubeio.NsenterWriter{}
    }

    var dockerClient dockertools.DockerInterface
    if s.ContainerRuntime == "docker" {
        dockerClient = dockertools.ConnectToDockerOrDie(s.DockerEndpoint, s.RuntimeRequestTimeout.Duration)
    } else {
        dockerClient = nil
    }

    return &kubelet.KubeletDeps{
        Auth:              nil, // default does not enforce auth[nz]
        CAdvisorInterface: nil, // cadvisor.New launches background processes (bg http.ListenAndServe, and some bg cleaners), not set here
        Cloud:             nil, // cloud provider might start background processes
        ContainerManager:  nil,
        DockerClient:      dockerClient,
        KubeClient:        nil,
        Mounter:           mounter,
        NetworkPlugins:    ProbeNetworkPlugins(s.NetworkPluginDir, s.CNIConfDir, s.CNIBinDir),
        OOMAdjuster:       oom.NewOOMAdjuster(),
        OSInterface:       kubecontainer.RealOS{},
        Writer:            writer,
        VolumePlugins:     ProbeVolumePlugins(s.VolumePluginDir),
        TLSOptions:        tlsOptions,
    }, nil
}

func ConnectToDockerOrDie(dockerEndpoint string, requestTimeout time.Duration) DockerInterface {
    if dockerEndpoint == "fake://" {
        return NewFakeDockerClient()
    }
    client, err := getDockerClient(dockerEndpoint)
    if err != nil {
        glog.Fatalf("Couldn't connect to docker: %v", err)
    }
    glog.Infof("Start docker client with request timeout=%v", requestTimeout)
    return newKubeDockerClient(client, requestTimeout)
}

// k8s.io/kubernetes/vendor/github.com/docker/engine-api/client/client.go

func getDockerClient(dockerEndpoint string) (*dockerapi.Client, error) {
    if len(dockerEndpoint) > 0 {
        glog.Infof("Connecting to docker on %s", dockerEndpoint)
        return dockerapi.NewClient(dockerEndpoint, "", nil, nil)
    }
    return dockerapi.NewEnvClient()
}

newKubeDockerClient implment
source path :k8s.io/kubernetes/pkg/kubelet/kubelet.go

func newKubeDockerClient(dockerClient *dockerapi.Client, requestTimeout time.Duration) DockerInterface {
    if requestTimeout == 0 {
        requestTimeout = defaultTimeout
    }

    k := &kubeDockerClient{
        client:  dockerClient,
        timeout: requestTimeout,
    }
    // Notice that this assumes that docker is running before kubelet is started.
    v, err := k.Version()
    if err != nil {
        glog.Errorf("failed to retrieve docker version: %v", err)
        glog.Warningf("Using empty version for docker client, this may sometimes cause compatibility issue.")
    } else {
        // Update client version with real api version.
        dockerClient.UpdateClientVersion(v.APIVersion)
    }
    return k
}

func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
    proto, addr, basePath, err := ParseHost(host)
    if err != nil {
        return nil, err
    }

    transport, err := transport.NewTransportWithHTTP(proto, addr, client)
    if err != nil {
        return nil, err
    }

    return &Client{
        proto:             proto,
        addr:              addr,
        basePath:          basePath,
        transport:         transport,
        version:           version,
        customHTTPHeaders: httpHeaders,
    }, nil
}

之前讲了如果没有传入”docker-endpoint”参数的话,默认值就是”unix:///var/run/docker.sock”.即host参数为该值。
ParseHost()先根据host进行解析,然后创建transport–>Client。
Client结构如下:

type Client struct {
    // proto holds the client protocol i.e. unix.
    proto string
    // addr holds the client address.
    addr string
    // basePath holds the path to prepend to the requests.
    basePath string
    // transport is the interface to send request with, it implements transport.Client.
    transport transport.Client
    // version of the server to talk to.
    version string
    // custom http headers configured by users.
    customHTTPHeaders map[string]string
}

而我们最终初始化返回了结构体kubeDockerClient,所以DockerInterface接口的实现,我们可以回到kubeDockerClient结构体所在文件pkg/kubelet/dockertools/kube_docker_client.go查看接口实现。

type DockerInterface interface {
    ListContainers(options dockertypes.ContainerListOptions) ([]dockertypes.Container, error)
    InspectContainer(id string) (*dockertypes.ContainerJSON, error)
    CreateContainer(dockertypes.ContainerCreateConfig) (*dockertypes.ContainerCreateResponse, error)
    StartContainer(id string) error
    StopContainer(id string, timeout int) error
    RemoveContainer(id string, opts dockertypes.ContainerRemoveOptions) error
    InspectImageByRef(imageRef string) (*dockertypes.ImageInspect, error)
    InspectImageByID(imageID string) (*dockertypes.ImageInspect, error)
    ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.Image, error)
    PullImage(image string, auth dockertypes.AuthConfig, opts dockertypes.ImagePullOptions) error
    RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDelete, error)
    ImageHistory(id string) ([]dockertypes.ImageHistory, error)
    Logs(string, dockertypes.ContainerLogsOptions, StreamOptions) error
    Version() (*dockertypes.Version, error)
    Info() (*dockertypes.Info, error)
    CreateExec(string, dockertypes.ExecConfig) (*dockertypes.ContainerExecCreateResponse, error)
    StartExec(string, dockertypes.ExecStartCheck, StreamOptions) error
    InspectExec(id string) (*dockertypes.ContainerExecInspect, error)
    AttachToContainer(string, dockertypes.ContainerAttachOptions, StreamOptions) error
    ResizeContainerTTY(id string, height, width int) error
    ResizeExecTTY(id string, height, width int) error
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值