mirror of
https://github.com/containers/podman.git
synced 2025-06-22 18:08:11 +08:00
Add ulimit annotation to kube gen & play
Add a podman ulimit annotation to kube generate and play. If a container has a container with ulimits set, kube gen will add those as an annotation to the generated yaml. If kube play encounters the ulimit annotation, it will set ulimits for the container being played. Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
This commit is contained in:
@ -140,6 +140,10 @@ const (
|
|||||||
// of the init container.
|
// of the init container.
|
||||||
InitContainerType = "io.podman.annotations.init.container.type"
|
InitContainerType = "io.podman.annotations.init.container.type"
|
||||||
|
|
||||||
|
// UlimitAnnotation is used by kube play when playing a kube yaml to specify the ulimits
|
||||||
|
// of the container
|
||||||
|
UlimitAnnotation = "io.podman.annotations.ulimit"
|
||||||
|
|
||||||
// MaxKubeAnnotation is the max length of annotations allowed by Kubernetes.
|
// MaxKubeAnnotation is the max length of annotations allowed by Kubernetes.
|
||||||
MaxKubeAnnotation = 63
|
MaxKubeAnnotation = 63
|
||||||
)
|
)
|
||||||
|
@ -531,6 +531,24 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctr.config.Spec.Process != nil {
|
||||||
|
var ulimitArr []string
|
||||||
|
defaultUlimits := util.DefaultContainerConfig().Ulimits()
|
||||||
|
for _, ulimit := range ctr.config.Spec.Process.Rlimits {
|
||||||
|
finalUlimit := strings.ToLower(strings.ReplaceAll(ulimit.Type, "RLIMIT_", "")) + "=" + strconv.Itoa(int(ulimit.Soft)) + ":" + strconv.Itoa(int(ulimit.Hard))
|
||||||
|
// compare ulimit with default list so we don't add it twice
|
||||||
|
if cutil.StringInSlice(finalUlimit, defaultUlimits) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ulimitArr = append(ulimitArr, finalUlimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ulimitArr) > 0 {
|
||||||
|
kubeAnnotations[define.UlimitAnnotation] = strings.Join(ulimitArr, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !ctr.HostNetwork() {
|
if !ctr.HostNetwork() {
|
||||||
hostNetwork = false
|
hostNetwork = false
|
||||||
}
|
}
|
||||||
|
@ -273,6 +273,18 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
|||||||
s.ResourceLimits.Memory.Reservation = &memoryRes
|
s.ResourceLimits.Memory.Reservation = &memoryRes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ulimitVal, ok := opts.Annotations[define.UlimitAnnotation]
|
||||||
|
if ok {
|
||||||
|
ulimits := strings.Split(ulimitVal, ",")
|
||||||
|
for _, ul := range ulimits {
|
||||||
|
parsed, err := units.ParseUlimit(ul)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.Rlimits = append(s.Rlimits, spec.POSIXRlimit{Type: parsed.Name, Soft: uint64(parsed.Soft), Hard: uint64(parsed.Hard)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: We don't understand why specgen does not take of this, but
|
// TODO: We don't understand why specgen does not take of this, but
|
||||||
// integration tests clearly pointed out that it was required.
|
// integration tests clearly pointed out that it was required.
|
||||||
imageData, err := opts.Image.Inspect(ctx, nil)
|
imageData, err := opts.Image.Inspect(ctx, nil)
|
||||||
|
@ -72,7 +72,6 @@ var _ = Describe("Podman kube generate", func() {
|
|||||||
Expect(pod.Spec.Containers[0].SecurityContext).To(BeNil())
|
Expect(pod.Spec.Containers[0].SecurityContext).To(BeNil())
|
||||||
Expect(pod.Spec.Containers[0].Env).To(BeNil())
|
Expect(pod.Spec.Containers[0].Env).To(BeNil())
|
||||||
Expect(pod).To(HaveField("Name", "top-pod"))
|
Expect(pod).To(HaveField("Name", "top-pod"))
|
||||||
Expect(pod.Annotations).To(HaveLen(0))
|
|
||||||
|
|
||||||
numContainers := 0
|
numContainers := 0
|
||||||
for range pod.Spec.Containers {
|
for range pod.Spec.Containers {
|
||||||
@ -1330,4 +1329,40 @@ USER test1`
|
|||||||
|
|
||||||
Expect(pod.Spec.Volumes[0].Secret).To(BeNil())
|
Expect(pod.Spec.Volumes[0].Secret).To(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman generate & play kube with --ulimit set", func() {
|
||||||
|
ctrName := "ulimit-ctr"
|
||||||
|
ctrNameInKubePod := ctrName + "-pod-" + ctrName
|
||||||
|
session1 := podmanTest.Podman([]string{"run", "-d", "--name", ctrName, "--ulimit", "nofile=1231:3123", ALPINE, "sleep", "1000"})
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
|
||||||
|
outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml")
|
||||||
|
kube := podmanTest.Podman([]string{"kube", "generate", ctrName, "-f", outputFile})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
b, err := os.ReadFile(outputFile)
|
||||||
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
pod := new(v1.Pod)
|
||||||
|
err = yaml.Unmarshal(b, pod)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(pod.Annotations).To(HaveKey(define.UlimitAnnotation))
|
||||||
|
Expect(pod.Annotations[define.UlimitAnnotation]).To(ContainSubstring("nofile=1231:3123"))
|
||||||
|
|
||||||
|
rm := podmanTest.Podman([]string{"pod", "rm", "-t", "0", "-f", ctrName})
|
||||||
|
rm.WaitWithDefaultTimeout()
|
||||||
|
Expect(rm).Should(Exit(0))
|
||||||
|
|
||||||
|
play := podmanTest.Podman([]string{"kube", "play", outputFile})
|
||||||
|
play.WaitWithDefaultTimeout()
|
||||||
|
Expect(play).Should(Exit(0))
|
||||||
|
|
||||||
|
inspect := podmanTest.Podman([]string{"inspect", ctrNameInKubePod})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("RLIMIT_NOFILE"))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("1231"))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("3123"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user