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:
Urvashi Mohnani
2023-02-06 10:13:11 -05:00
parent 86da741d89
commit 35d16ea027
4 changed files with 70 additions and 1 deletions

View File

@ -140,6 +140,10 @@ const (
// of the init container.
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 = 63
)

View File

@ -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() {
hostNetwork = false
}

View File

@ -273,6 +273,18 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
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
// integration tests clearly pointed out that it was required.
imageData, err := opts.Image.Inspect(ctx, nil)

View File

@ -72,7 +72,6 @@ var _ = Describe("Podman kube generate", func() {
Expect(pod.Spec.Containers[0].SecurityContext).To(BeNil())
Expect(pod.Spec.Containers[0].Env).To(BeNil())
Expect(pod).To(HaveField("Name", "top-pod"))
Expect(pod.Annotations).To(HaveLen(0))
numContainers := 0
for range pod.Spec.Containers {
@ -1330,4 +1329,40 @@ USER test1`
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"))
})
})