mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 23:15:14 +00:00
Merge pull request #1458 from brendandburns/dontpull
Add the ability to turn off image pulling.
This commit is contained in:
commit
db49dc0012
@ -17,6 +17,8 @@ limitations under the License.
|
||||
package api
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
@ -181,6 +183,38 @@ type LivenessProbe struct {
|
||||
InitialDelaySeconds int64 `yaml:"initialDelaySeconds,omitempty" json:"initialDelaySeconds,omitempty"`
|
||||
}
|
||||
|
||||
// PullPolicy describes a policy for if/when to pull a container image
|
||||
type PullPolicy string
|
||||
|
||||
const (
|
||||
// Always attempt to pull the latest image. Container will fail If the pull fails.
|
||||
PullAlways PullPolicy = "PullAlways"
|
||||
// Never pull an image, only use a local image. Container will fail if the image isn't present
|
||||
PullNever PullPolicy = "PullNever"
|
||||
// Pull if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
|
||||
PullIfNotPresent PullPolicy = "PullIfNotPresent"
|
||||
)
|
||||
|
||||
func IsPullAlways(p PullPolicy) bool {
|
||||
// Default to pull always
|
||||
if len(p) == 0 {
|
||||
return true
|
||||
}
|
||||
return pullPoliciesEqual(p, PullAlways)
|
||||
}
|
||||
|
||||
func IsPullNever(p PullPolicy) bool {
|
||||
return pullPoliciesEqual(p, PullNever)
|
||||
}
|
||||
|
||||
func IsPullIfNotPresent(p PullPolicy) bool {
|
||||
return pullPoliciesEqual(p, PullIfNotPresent)
|
||||
}
|
||||
|
||||
func pullPoliciesEqual(p1, p2 PullPolicy) bool {
|
||||
return strings.ToLower(string(p1)) == strings.ToLower(string(p2))
|
||||
}
|
||||
|
||||
// Container represents a single container that is expected to be run on the host.
|
||||
type Container struct {
|
||||
// Required: This must be a DNS_LABEL. Each container in a pod must
|
||||
@ -203,6 +237,8 @@ type Container struct {
|
||||
Lifecycle *Lifecycle `yaml:"lifecycle,omitempty" json:"lifecycle,omitempty"`
|
||||
// Optional: Default to false.
|
||||
Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"`
|
||||
// Optional: Policy for pulling images for this container
|
||||
ImagePullPolicy PullPolicy `json:"imagePullPolicy" yaml:"imagePullPolicy"`
|
||||
}
|
||||
|
||||
// Handler defines a specific action that should be taken
|
||||
|
@ -191,6 +191,18 @@ type LivenessProbe struct {
|
||||
InitialDelaySeconds int64 `yaml:"initialDelaySeconds,omitempty" json:"initialDelaySeconds,omitempty"`
|
||||
}
|
||||
|
||||
// PullPolicy describes a policy for if/when to pull a container image
|
||||
type PullPolicy string
|
||||
|
||||
const (
|
||||
// Always attempt to pull the latest image. Container will fail If the pull fails.
|
||||
PullAlways PullPolicy = "PullAlways"
|
||||
// Never pull an image, only use a local image. Container will fail if the image isn't present
|
||||
PullNever PullPolicy = "PullNever"
|
||||
// Pull if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
|
||||
PullIfNotPresent PullPolicy = "PullIfNotPresent"
|
||||
)
|
||||
|
||||
// Container represents a single container that is expected to be run on the host.
|
||||
type Container struct {
|
||||
// Required: This must be a DNS_LABEL. Each container in a pod must
|
||||
@ -213,6 +225,8 @@ type Container struct {
|
||||
Lifecycle *Lifecycle `yaml:"lifecycle,omitempty" json:"lifecycle,omitempty"`
|
||||
// Optional: Default to false.
|
||||
Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"`
|
||||
// Optional: Policy for pulling images for this container
|
||||
ImagePullPolicy PullPolicy `json:"imagePullPolicy" yaml:"imagePullPolicy"`
|
||||
}
|
||||
|
||||
// Handler defines a specific action that should be taken
|
||||
|
@ -190,6 +190,18 @@ type LivenessProbe struct {
|
||||
InitialDelaySeconds int64 `yaml:"initialDelaySeconds,omitempty" json:"initialDelaySeconds,omitempty"`
|
||||
}
|
||||
|
||||
// PullPolicy describes a policy for if/when to pull a container image
|
||||
type PullPolicy string
|
||||
|
||||
const (
|
||||
// Always attempt to pull the latest image. Container will fail If the pull fails.
|
||||
PullAlways PullPolicy = "PullAlways"
|
||||
// Never pull an image, only use a local image. Container will fail if the image isn't present
|
||||
PullNever PullPolicy = "PullNever"
|
||||
// Pull if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
|
||||
PullIfNotPresent PullPolicy = "PullIfNotPresent"
|
||||
)
|
||||
|
||||
// Container represents a single container that is expected to be run on the host.
|
||||
type Container struct {
|
||||
// Required: This must be a DNS_LABEL. Each container in a pod must
|
||||
@ -212,6 +224,8 @@ type Container struct {
|
||||
Lifecycle *Lifecycle `yaml:"lifecycle,omitempty" json:"lifecycle,omitempty"`
|
||||
// Optional: Default to false.
|
||||
Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"`
|
||||
// Optional: Policy for pulling images for this container
|
||||
ImagePullPolicy PullPolicy `json:"imagePullPolicy" yaml:"imagePullPolicy"`
|
||||
}
|
||||
|
||||
// Handler defines a specific action that should be taken
|
||||
|
@ -226,6 +226,18 @@ type LivenessProbe struct {
|
||||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty" yaml:"initialDelaySeconds,omitempty"`
|
||||
}
|
||||
|
||||
// PullPolicy describes a policy for if/when to pull a container image
|
||||
type PullPolicy string
|
||||
|
||||
const (
|
||||
// Always attempt to pull the latest image. Container will fail If the pull fails.
|
||||
PullAlways PullPolicy = "PullAlways"
|
||||
// Never pull an image, only use a local image. Container will fail if the image isn't present
|
||||
PullNever PullPolicy = "PullNever"
|
||||
// Pull if the image isn't present on disk. Container will fail if the image isn't present and the pull fails.
|
||||
PullIfNotPresent PullPolicy = "PullIfNotPresent"
|
||||
)
|
||||
|
||||
// Container represents a single container that is expected to be run on the host.
|
||||
type Container struct {
|
||||
// Required: This must be a DNS_LABEL. Each container in a pod must
|
||||
@ -248,6 +260,8 @@ type Container struct {
|
||||
Lifecycle *Lifecycle `json:"lifecycle,omitempty" yaml:"lifecycle,omitempty"`
|
||||
// Optional: Default to false.
|
||||
Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"`
|
||||
// Optional: Policy for pulling images for this container
|
||||
ImagePullPolicy PullPolicy `json:"imagePullPolicy" yaml:"imagePullPolicy"`
|
||||
}
|
||||
|
||||
// Handler defines a specific action that should be taken
|
||||
|
@ -47,6 +47,7 @@ type DockerInterface interface {
|
||||
CreateContainer(docker.CreateContainerOptions) (*docker.Container, error)
|
||||
StartContainer(id string, hostConfig *docker.HostConfig) error
|
||||
StopContainer(id string, timeout uint) error
|
||||
InspectImage(image string) (*docker.Image, error)
|
||||
PullImage(opts docker.PullImageOptions, auth docker.AuthConfiguration) error
|
||||
Logs(opts docker.LogsOptions) error
|
||||
}
|
||||
@ -57,6 +58,7 @@ type DockerID string
|
||||
// DockerPuller is an abstract interface for testability. It abstracts image pull operations.
|
||||
type DockerPuller interface {
|
||||
Pull(image string) error
|
||||
IsImagePresent(image string) (bool, error)
|
||||
}
|
||||
|
||||
// dockerPuller is the default implementation of DockerPuller.
|
||||
@ -148,6 +150,24 @@ func (p throttledDockerPuller) Pull(image string) error {
|
||||
return fmt.Errorf("pull QPS exceeded.")
|
||||
}
|
||||
|
||||
func (p dockerPuller) IsImagePresent(name string) (bool, error) {
|
||||
image, _ := parseImageName(name)
|
||||
_, err := p.client.InspectImage(image)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
// This is super brittle, but its the best we got.
|
||||
// TODO: Land code in the docker client to use docker.Error here instead.
|
||||
if err.Error() == "no such image" {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func (p throttledDockerPuller) IsImagePresent(name string) (bool, error) {
|
||||
return p.puller.IsImagePresent(name)
|
||||
}
|
||||
|
||||
// DockerContainers is a map of containers
|
||||
type DockerContainers map[DockerID]*docker.APIContainers
|
||||
|
||||
|
@ -130,6 +130,10 @@ func (f *FakeDockerClient) PullImage(opts docker.PullImageOptions, auth docker.A
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) InspectImage(name string) (*docker.Image, error) {
|
||||
return nil, f.Err
|
||||
}
|
||||
|
||||
// FakeDockerPuller is a stub implementation of DockerPuller.
|
||||
type FakeDockerPuller struct {
|
||||
sync.Mutex
|
||||
@ -153,3 +157,7 @@ func (f *FakeDockerPuller) Pull(image string) (err error) {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *FakeDockerPuller) IsImagePresent(name string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
@ -528,9 +528,18 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers dockertools.DockerContaine
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Container with name %s--%s--%s doesn't exist, creating %#v", podFullName, uuid, container.Name, container)
|
||||
if err := kl.dockerPuller.Pull(container.Image); err != nil {
|
||||
glog.Errorf("Failed to pull image %s: %v skipping pod %s container %s.", container.Image, err, podFullName, container.Name)
|
||||
continue
|
||||
if !api.IsPullNever(container.ImagePullPolicy) {
|
||||
present, err := kl.dockerPuller.IsImagePresent(container.Image)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to inspect image: %s: %#v skipping pod %s container %s", container.Image, err, podFullName, container.Name)
|
||||
continue
|
||||
}
|
||||
if api.IsPullAlways(container.ImagePullPolicy) || !present {
|
||||
if err := kl.dockerPuller.Pull(container.Image); err != nil {
|
||||
glog.Errorf("Failed to pull image %s: %v skipping pod %s container %s.", container.Image, err, podFullName, container.Name)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO(dawnchen): Check RestartPolicy.DelaySeconds before restart a container
|
||||
containerID, err := kl.runContainer(pod, &container, podVolumes, "container:"+string(netID))
|
||||
|
Loading…
Reference in New Issue
Block a user