kubelet拉取镜像是用许多密钥尝试去拉取,kubelet拉取私有镜像除了可以在yaml里面配置私有镜像仓库密钥以外,也可以在运行本地通过配置文件配置,下面就解说一下拉取过程。
//pkg/kubelet/kuberuntime/kuberuntime_image.go
func (m *kubeGenericRuntimeManager) PullImage(image kubecontainer.ImageSpec, pullSecrets []v1.Secret) (string, error) {
//如果没有在yaml里面配置私有仓库密钥pullSecrets长度就是0
img := image.Image
repoToPull, _, _, err := parsers.ParseImageName(img)
if err != nil {
return "", err
}
//下面这一句是根据pullSecrets生成docker密钥的过程如果没有yaml没有配置那么用的是配置文件配置的密钥
keyring, err := credentialprovider.MakeDockerKeyring(pullSecrets, m.keyring)
if err != nil {
return "", err
}
imgSpec := &runtimeapi.ImageSpec{Image: img}
creds, withCredentials := keyring.Lookup(repoToPull)
if !withCredentials {
glog.V(3).Infof("Pulling image %q without credentials", img)
imageRef, err := m.imageService.PullImage(imgSpec, nil)
if err != nil {
glog.Errorf("Pull image %q failed: %v", img, err)
return "", err
}
return imageRef, nil
}
var pullErrs []error
//根据获取的密钥进行尝试
for _, currentCreds := range creds {
authConfig := credentialprovider.LazyProvide(currentCreds)
auth := &runtimeapi.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
Auth: authConfig.Auth,
ServerAddress: authConfig.ServerAddress,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
}
imageRef, err := m.imageService.PullImage(imgSpec, auth)
// If there was no error, return success
if err == nil {
return imageRef, nil
}
pullErrs = append(pullErrs, err)
}
return "", utilerrors.NewAggregate(pullErrs)
}
获取本地密钥过程:
func DefaultDockercfgPaths() []string {
return []string{GetPreferredDockercfgPath(), workingDirPath, homeDirPath, rootDirPath}
}
//DefaultDockerConfigJSONPaths returns default search paths of .docker/config.json
func DefaultDockerConfigJSONPaths() []string {
return []string{GetPreferredDockercfgPath(), workingDirPath, homeJsonDirPath, rootJsonDirPath}
}
// ReadDockercfgFile attempts to read a legacy dockercfg file from the given paths.
// if searchPaths is empty, the default paths are used.
func ReadDockercfgFile(searchPaths []string) (cfg DockerConfig, err error) {
if len(searchPaths) == 0 {
searchPaths = DefaultDockercfgPaths()
}
for _, configPath := range searchPaths {
absDockerConfigFileLocation, err := filepath.Abs(filepath.Join(configPath, configFileName))
if err != nil {
glog.Errorf("while trying to canonicalize %s: %v", configPath, err)
continue
}
glog.V(4).Infof("looking for .dockercfg at %s", absDockerConfigFileLocation)
contents, err := ioutil.ReadFile(absDockerConfigFileLocation)
if os.IsNotExist(err) {
continue
}
if err != nil {
glog.V(4).Infof("while trying to read %s: %v", absDockerConfigFileLocation, err)
continue
}
cfg, err := readDockerConfigFileFromBytes(contents)
if err == nil {
glog.V(4).Infof("found .dockercfg at %s", absDockerConfigFileLocation)
return cfg, nil
}
}
return nil, fmt.Errorf("couldn't find valid .dockercfg after checking in %v", searchPaths)
}
// ReadDockerConfigJSONFile attempts to read a docker config.json file from the given paths.
// if searchPaths is empty, the default paths are used.
func ReadDockerConfigJSONFile(searchPaths []string) (cfg DockerConfig, err error) {
if len(searchPaths) == 0 {
searchPaths = DefaultDockerConfigJSONPaths()
}
for _, configPath := range searchPaths {
absDockerConfigFileLocation, err := filepath.Abs(filepath.Join(configPath, configJsonFileName))
if err != nil {
glog.Errorf("while trying to canonicalize %s: %v", configPath, err)
continue
}
glog.V(4).Infof("looking for %s at %s", configJsonFileName, absDockerConfigFileLocation)
cfg, err = ReadSpecificDockerConfigJsonFile(absDockerConfigFileLocation)
if err != nil {
if !os.IsNotExist(err) {
glog.V(4).Infof("while trying to read %s: %v", absDockerConfigFileLocation, err)
}
continue
}
glog.V(4).Infof("found valid %s at %s", configJsonFileName, absDockerConfigFileLocation)
return cfg, nil
}
return nil, fmt.Errorf("couldn't find valid %s after checking in %v", configJsonFileName, searchPaths)
}
//ReadSpecificDockerConfigJsonFile attempts to read docker configJSON from a given file path.
func ReadSpecificDockerConfigJsonFile(filePath string) (cfg DockerConfig, err error) {
var contents []byte
if contents, err = ioutil.ReadFile(filePath); err != nil {
return nil, err
}
return readDockerConfigJsonFileFromBytes(contents)
}
func ReadDockerConfigFile() (cfg DockerConfig, err error) {
if cfg, err := ReadDockerConfigJSONFile(nil); err == nil {
return cfg, nil
}
// Can't find latest config file so check for the old one
return ReadDockercfgFile(nil)
}
密钥分为两种文件类型一种是config.json另一种是.dockercfg,根据这两种文件可以从不同的目录下读取,例如:
/var/lib/kubelet/config.json
/root/.docker/config.json
/var/lib/kubelet/.dockercfg
/root/.docker/.dockercfg
...
所以只要上述的文件只要有私有仓库的登录信息就能达到拉取私有仓库的目的。
网友评论