mirror of
https://github.com/containers/podman
synced 2024-10-21 01:34:37 +00:00
pod create: remove need for pause image
So far, the infra containers of pods required pulling down an image rendering pods not usable in disconnected environments. Instead, build an image locally which uses local pause binary. Fixes: #10354 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
parent
9d2b8d2791
commit
75f478c08b
|
@ -372,15 +372,10 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
|
|||
}
|
||||
|
||||
infraOpts := entities.ContainerCreateOptions{ImageVolume: "bind", Net: netOpts, Quiet: true}
|
||||
rawImageName := config.DefaultInfraImage
|
||||
name, err := PullImage(rawImageName, infraOpts)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
imageName := name
|
||||
imageName := config.DefaultInfraImage
|
||||
podGen.InfraImage = imageName
|
||||
podGen.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
|
||||
podGen.InfraContainerSpec.RawImageName = rawImageName
|
||||
podGen.InfraContainerSpec.RawImageName = imageName
|
||||
podGen.InfraContainerSpec.NetworkOptions = podGen.NetworkOptions
|
||||
err = specgenutil.FillOutSpecGen(podGen.InfraContainerSpec, &infraOpts, []string{})
|
||||
if err != nil {
|
||||
|
|
|
@ -242,16 +242,6 @@ func create(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
if createOptions.Infra {
|
||||
rawImageName = img
|
||||
if !infraOptions.RootFS {
|
||||
curr := infraOptions.Quiet
|
||||
infraOptions.Quiet = true
|
||||
name, err := containers.PullImage(imageName, infraOptions)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
imageName = name
|
||||
infraOptions.Quiet = curr
|
||||
}
|
||||
podSpec.InfraImage = imageName
|
||||
if infraOptions.Entrypoint != nil {
|
||||
createOptions.InfraCommand = infraOptions.Entrypoint
|
||||
|
|
|
@ -67,7 +67,7 @@ func version(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
if err := tmpl.Execute(w, versions); err != nil {
|
||||
// On Failure, assume user is using older version of podman version --format and check client
|
||||
row = strings.Replace(row, ".Server.", ".", 1)
|
||||
row = strings.ReplaceAll(row, ".Server.", ".")
|
||||
tmpl, err := report.NewTemplate("version 1.0.0").Parse(row)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -112,7 +112,7 @@ The command that will be run to start the infra container. Default: "/pause".
|
|||
|
||||
#### **--infra-image**=*image*
|
||||
|
||||
The image that will be created for the infra container. Default: "k8s.gcr.io/pause:3.1".
|
||||
The custom image that will be used for the infra container. Unless specified, Podman builds a custom local image which does not require pulling down an image.
|
||||
|
||||
#### **--infra-name**=*name*
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/libpod/network/types"
|
||||
"github.com/containers/podman/v3/pkg/env"
|
||||
|
@ -468,11 +469,23 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
|
|||
|
||||
kubeContainer.Name = removeUnderscores(c.Name())
|
||||
_, image := c.Image()
|
||||
|
||||
// The infra container may have been created with an overlay root FS
|
||||
// instead of an infra image. If so, set the imageto the default K8s
|
||||
// pause one and make sure it's in the storage by pulling it down if
|
||||
// missing.
|
||||
if image == "" && c.IsInfra() {
|
||||
image = config.DefaultInfraImage
|
||||
if _, err := c.runtime.libimageRuntime.Pull(ctx, image, config.PullPolicyMissing, nil); err != nil {
|
||||
return kubeContainer, nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
kubeContainer.Image = image
|
||||
kubeContainer.Stdin = c.Stdin()
|
||||
img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil)
|
||||
if err != nil {
|
||||
return kubeContainer, kubeVolumes, nil, annotations, err
|
||||
return kubeContainer, kubeVolumes, nil, annotations, fmt.Errorf("looking up image %q of container %q: %w", image, c.ID(), err)
|
||||
}
|
||||
imgData, err := img.Inspect(ctx, nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
package libpod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/libimage"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/podman/v3/libpod"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/api/handlers"
|
||||
|
@ -67,20 +64,6 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
|
|||
imageName = config.DefaultInfraImage
|
||||
rawImageName = config.DefaultInfraImage
|
||||
}
|
||||
curr := infraOptions.Quiet
|
||||
infraOptions.Quiet = true
|
||||
pullOptions := &libimage.PullOptions{}
|
||||
pulledImages, err := runtime.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, pullOptions)
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "could not pull image"))
|
||||
return
|
||||
}
|
||||
if _, err := alltransports.ParseImageName(imageName); err == nil {
|
||||
if len(pulledImages) != 0 {
|
||||
imageName = pulledImages[0].ID()
|
||||
}
|
||||
}
|
||||
infraOptions.Quiet = curr
|
||||
psg.InfraImage = imageName
|
||||
psg.InfraContainerSpec.Image = imageName
|
||||
psg.InfraContainerSpec.RawImageName = rawImageName
|
||||
|
|
|
@ -2,8 +2,12 @@ package generate
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
buildahDefine "github.com/containers/buildah/define"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v3/libpod"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
|
@ -14,10 +18,102 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func buildPauseImage(rt *libpod.Runtime, rtConfig *config.Config) (string, error) {
|
||||
version, err := define.GetVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imageName := fmt.Sprintf("localhost/podman-pause:%s-%d", version.Version, version.Built)
|
||||
|
||||
// First check if the image has already been built.
|
||||
if _, _, err := rt.LibimageRuntime().LookupImage(imageName, nil); err == nil {
|
||||
return imageName, nil
|
||||
}
|
||||
|
||||
// NOTE: Having the pause binary in its own directory keeps the door
|
||||
// open for replacing the image building with using an overlay root FS.
|
||||
// The latter turned out to be complex and error prone (see #11956) but
|
||||
// we may be able to come up with a proper solution at a later point in
|
||||
// time.
|
||||
pausePath, err := rtConfig.FindHelperBinary("pause/pause", false)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("finding pause binary: %w", err)
|
||||
}
|
||||
|
||||
buildContent := fmt.Sprintf(`FROM scratch
|
||||
COPY %s /pause
|
||||
ENTRYPOINT ["/pause"]`, pausePath)
|
||||
|
||||
tmpF, err := ioutil.TempFile("", "pause.containerfile")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err := tmpF.WriteString(buildContent); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := tmpF.Close(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer os.Remove(tmpF.Name())
|
||||
|
||||
buildOptions := buildahDefine.BuildOptions{
|
||||
CommonBuildOpts: &buildahDefine.CommonBuildOptions{},
|
||||
Output: imageName,
|
||||
Quiet: true,
|
||||
IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
|
||||
}
|
||||
if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return imageName, nil
|
||||
}
|
||||
|
||||
func pullOrBuildInfraImage(p *entities.PodSpec, rt *libpod.Runtime) error {
|
||||
if p.PodSpecGen.NoInfra {
|
||||
return nil
|
||||
}
|
||||
|
||||
rtConfig, err := rt.GetConfigNoCopy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// NOTE: we need pull down the infra image if it was explicitly set by
|
||||
// the user (or containers.conf) to the non-default one.
|
||||
imageName := p.PodSpecGen.InfraImage
|
||||
if imageName == "" {
|
||||
imageName = rtConfig.Engine.InfraImage
|
||||
}
|
||||
|
||||
if imageName != config.DefaultInfraImage {
|
||||
_, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
name, err := buildPauseImage(rt, rtConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("building local pause image: %w", err)
|
||||
}
|
||||
imageName = name
|
||||
}
|
||||
|
||||
p.PodSpecGen.InfraImage = imageName
|
||||
p.PodSpecGen.InfraContainerSpec.RawImageName = imageName
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
|
||||
if err := p.PodSpecGen.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := pullOrBuildInfraImage(p, rt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
|
||||
var err error
|
||||
p.PodSpecGen.InfraContainerSpec, err = MapSpec(&p.PodSpecGen)
|
||||
|
@ -35,7 +131,6 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
|
|||
return nil, err
|
||||
}
|
||||
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
|
||||
p.PodSpecGen.InfraContainerSpec.ContainerCreateCommand = []string{} // we do NOT want os.Args as the command, will display the pod create cmd
|
||||
if p.PodSpecGen.InfraContainerSpec.Name == "" {
|
||||
p.PodSpecGen.InfraContainerSpec.Name = pod.ID()[:12] + "-infra"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
. "github.com/containers/podman/v3/test/utils"
|
||||
|
@ -1120,24 +1119,6 @@ var _ = Describe("Podman play kube", func() {
|
|||
Expect(label).To(ContainSubstring("unconfined_u:system_r:spc_t:s0"))
|
||||
})
|
||||
|
||||
It("podman play kube should use default infra_image", func() {
|
||||
err := writeYaml(checkInfraImagePodYaml, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube).Should(Exit(0))
|
||||
|
||||
podInspect := podmanTest.Podman([]string{"inspect", "check-infra-image", "--format", "{{ .InfraContainerID }}"})
|
||||
podInspect.WaitWithDefaultTimeout()
|
||||
infraContainerID := podInspect.OutputToString()
|
||||
|
||||
conInspect := podmanTest.Podman([]string{"inspect", infraContainerID, "--format", "{{ .ImageName }}"})
|
||||
conInspect.WaitWithDefaultTimeout()
|
||||
infraContainerImage := conInspect.OutputToString()
|
||||
Expect(infraContainerImage).To(Equal(config.DefaultInfraImage))
|
||||
})
|
||||
|
||||
It("podman play kube --no-host", func() {
|
||||
err := writeYaml(checkInfraImagePodYaml, kubeYaml)
|
||||
Expect(err).To(BeNil())
|
||||
|
|
|
@ -60,6 +60,10 @@ function teardown() {
|
|||
run_podman pod rm -f -t 0 $podid
|
||||
}
|
||||
|
||||
function rm_podman_pause_image() {
|
||||
run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
|
||||
run_podman rmi -f "localhost/podman-pause:$output"
|
||||
}
|
||||
|
||||
@test "podman pod - communicating between pods" {
|
||||
podname=pod$(random_string)
|
||||
|
@ -100,19 +104,14 @@ function teardown() {
|
|||
# Clean up. First the nc -l container...
|
||||
run_podman rm $cid1
|
||||
|
||||
# ...then, from pause container, find the image ID of the pause image...
|
||||
run_podman pod inspect --format '{{(index .Containers 0).ID}}' $podname
|
||||
pause_cid="$output"
|
||||
run_podman container inspect --format '{{.Image}}' $pause_cid
|
||||
pause_iid="$output"
|
||||
|
||||
# ...then rm the pod, then rmi the pause image so we don't leave strays.
|
||||
run_podman pod rm $podname
|
||||
run_podman rmi $pause_iid
|
||||
|
||||
# Pod no longer exists
|
||||
run_podman 1 pod exists $podid
|
||||
run_podman 1 pod exists $podname
|
||||
|
||||
rm_podman_pause_image
|
||||
}
|
||||
|
||||
@test "podman pod - communicating via /dev/shm " {
|
||||
|
@ -133,6 +132,10 @@ function teardown() {
|
|||
# Pod no longer exists
|
||||
run_podman 1 pod exists $podid
|
||||
run_podman 1 pod exists $podname
|
||||
|
||||
# Pause image hasn't been pulled
|
||||
run_podman 1 image exists k8s.gcr.io/pause:3.5
|
||||
rm_podman_pause_image
|
||||
}
|
||||
|
||||
# Random byte
|
||||
|
@ -303,16 +306,25 @@ EOF
|
|||
run_podman rm $cid
|
||||
run_podman pod rm -t 0 -f mypod
|
||||
run_podman rmi $infra_image
|
||||
|
||||
}
|
||||
|
||||
@test "podman pod create should fail when infra-name is already in use" {
|
||||
local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
|
||||
run_podman pod create --infra-name "$infra_name"
|
||||
local pod_name="$(random_string 10 | tr A-Z a-z)"
|
||||
|
||||
# Note that the internal pause image is built even when --infra-image is
|
||||
# set to the K8s one.
|
||||
run_podman pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5"
|
||||
run_podman '?' pod create --infra-name "$infra_name"
|
||||
if [ $status -eq 0 ]; then
|
||||
die "Podman should fail when user try to create two pods with the same infra-name value"
|
||||
fi
|
||||
run_podman pod rm -f $pod_name
|
||||
run_podman images -a
|
||||
|
||||
# Pause image hasn't been pulled
|
||||
run_podman 1 image exists k8s.gcr.io/pause:3.5
|
||||
rm_podman_pause_image
|
||||
}
|
||||
|
||||
# vim: filetype=sh
|
||||
|
|
Loading…
Reference in a new issue