mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-05 11:36:56 +00:00
Merge pull request #458 from harche/without_devices
virtcontainers: Add support for ephemeral volumes
This commit is contained in:
commit
81c073f67d
@ -109,7 +109,6 @@ func create(containerID, bundlePath, console, pidFilePath string, detach bool,
|
||||
disableOutput := noNeedForOutput(detach, ociSpec.Process.Terminal)
|
||||
|
||||
var process vc.Process
|
||||
|
||||
switch containerType {
|
||||
case vc.PodSandbox:
|
||||
process, err = createSandbox(ociSpec, runtimeConfig, containerID, bundlePath, console, disableOutput)
|
||||
@ -255,9 +254,25 @@ func createSandbox(ociSpec oci.CompatOCISpec, runtimeConfig oci.RuntimeConfig,
|
||||
return containers[0].Process(), nil
|
||||
}
|
||||
|
||||
// setEphemeralStorageType sets the mount type to 'ephemeral'
|
||||
// if the mount source path is provisioned by k8s for ephemeral storage.
|
||||
// For the given pod ephemeral volume is created only once
|
||||
// backed by tmpfs inside the VM. For successive containers
|
||||
// of the same pod the already existing volume is reused.
|
||||
func setEphemeralStorageType(ociSpec oci.CompatOCISpec) oci.CompatOCISpec {
|
||||
for idx, mnt := range ociSpec.Mounts {
|
||||
if IsEphemeralStorage(mnt.Source) {
|
||||
ociSpec.Mounts[idx].Type = "ephemeral"
|
||||
}
|
||||
}
|
||||
return ociSpec
|
||||
}
|
||||
|
||||
func createContainer(ociSpec oci.CompatOCISpec, containerID, bundlePath,
|
||||
console string, disableOutput bool) (vc.Process, error) {
|
||||
|
||||
ociSpec = setEphemeralStorageType(ociSpec)
|
||||
|
||||
contConfig, err := oci.ContainerConfig(ociSpec, bundlePath, containerID, console, disableOutput)
|
||||
if err != nil {
|
||||
return vc.Process{}, err
|
||||
|
@ -1010,6 +1010,24 @@ func TestCreateCreateContainerFail(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetEphemeralStorageType(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
ociSpec := oci.CompatOCISpec{}
|
||||
var ociMounts []specs.Mount
|
||||
mount := specs.Mount{
|
||||
Source: "/var/lib/kubelet/pods/366c3a77-4869-11e8-b479-507b9ddd5ce4/volumes/kubernetes.io~empty-dir/cache-volume",
|
||||
}
|
||||
|
||||
ociMounts = append(ociMounts, mount)
|
||||
ociSpec.Mounts = ociMounts
|
||||
ociSpec = setEphemeralStorageType(ociSpec)
|
||||
|
||||
mountType := ociSpec.Mounts[0].Type
|
||||
assert.Equal(mountType, "ephemeral",
|
||||
"Unexpected mount type, got %s expected ephemeral", mountType)
|
||||
}
|
||||
|
||||
func TestCreateCreateContainer(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
25
cli/utils.go
25
cli/utils.go
@ -15,7 +15,10 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const unknown = "<<unknown>>"
|
||||
const (
|
||||
unknown = "<<unknown>>"
|
||||
k8sEmptyDir = "kubernetes.io~empty-dir"
|
||||
)
|
||||
|
||||
// variables to allow tests to modify the values
|
||||
var (
|
||||
@ -43,6 +46,26 @@ func getFileContents(file string) (string, error) {
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
// IsEphemeralStorage returns true if the given path
|
||||
// to the storage belongs to kubernetes ephemeral storage
|
||||
//
|
||||
// This method depends on a specific path used by k8s
|
||||
// to detect if it's of type ephemeral. As of now,
|
||||
// this is a very k8s specific solution that works
|
||||
// but in future there should be a better way for this
|
||||
// method to determine if the path is for ephemeral
|
||||
// volume type
|
||||
func IsEphemeralStorage(path string) bool {
|
||||
splitSourceSlice := strings.Split(path, "/")
|
||||
if len(splitSourceSlice) > 1 {
|
||||
storageType := splitSourceSlice[len(splitSourceSlice)-2]
|
||||
if storageType == k8sEmptyDir {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getKernelVersion() (string, error) {
|
||||
contents, err := getFileContents(procVersion)
|
||||
if err != nil {
|
||||
|
@ -38,6 +38,20 @@ func TestFileExists(t *testing.T) {
|
||||
fmt.Sprintf("File %q should exist", file))
|
||||
}
|
||||
|
||||
func TestIsEphemeralStorage(t *testing.T) {
|
||||
sampleEphePath := "/var/lib/kubelet/pods/366c3a75-4869-11e8-b479-507b9ddd5ce4/volumes/kubernetes.io~empty-dir/cache-volume"
|
||||
isEphe := IsEphemeralStorage(sampleEphePath)
|
||||
if !isEphe {
|
||||
t.Fatalf("Unable to correctly determine volume type")
|
||||
}
|
||||
|
||||
sampleEphePath = "/var/lib/kubelet/pods/366c3a75-4869-11e8-b479-507b9ddd5ce4/volumes/cache-volume"
|
||||
isEphe = IsEphemeralStorage(sampleEphePath)
|
||||
if isEphe {
|
||||
t.Fatalf("Unable to correctly determine volume type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFileContents(t *testing.T) {
|
||||
type testData struct {
|
||||
contents string
|
||||
|
@ -52,6 +52,7 @@ var (
|
||||
sharedDir9pOptions = []string{"trans=virtio,version=9p2000.L", "nodev"}
|
||||
shmDir = "shm"
|
||||
kataEphemeralDevType = "ephemeral"
|
||||
ephemeralPath = filepath.Join(kataGuestSandboxDir, kataEphemeralDevType)
|
||||
)
|
||||
|
||||
// KataAgentConfig is a structure storing information needed
|
||||
@ -803,6 +804,9 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
epheStorages := k.handleEphemeralStorage(ociSpec.Mounts)
|
||||
ctrStorages = append(ctrStorages, epheStorages...)
|
||||
|
||||
// We replace all OCI mount sources that match our container mount
|
||||
// with the right source path (The guest one).
|
||||
if err = k.replaceOCIMountSource(ociSpec, newMounts); err != nil {
|
||||
@ -868,6 +872,29 @@ func (k *kataAgent) createContainer(sandbox *Sandbox, c *Container) (p *Process,
|
||||
k.state.URL, c.config.Cmd, createNSList, enterNSList)
|
||||
}
|
||||
|
||||
// handleEphemeralStorage handles ephemeral storages by
|
||||
// creating a Storage from corresponding source of the mount point
|
||||
func (k *kataAgent) handleEphemeralStorage(mounts []specs.Mount) []*grpc.Storage {
|
||||
var epheStorages []*grpc.Storage
|
||||
for idx, mnt := range mounts {
|
||||
if mnt.Type == kataEphemeralDevType {
|
||||
// Set the mount source path to a path that resides inside the VM
|
||||
mounts[idx].Source = filepath.Join(ephemeralPath, filepath.Base(mnt.Source))
|
||||
|
||||
// Create a storage struct so that kata agent is able to create
|
||||
// tmpfs backed volume inside the VM
|
||||
epheStorage := &grpc.Storage{
|
||||
Driver: kataEphemeralDevType,
|
||||
Source: "tmpfs",
|
||||
Fstype: "tmpfs",
|
||||
MountPoint: mounts[idx].Source,
|
||||
}
|
||||
epheStorages = append(epheStorages, epheStorage)
|
||||
}
|
||||
}
|
||||
return epheStorages
|
||||
}
|
||||
|
||||
// handleBlockVolumes handles volumes that are block devices files
|
||||
// by passing the block devices as Storage to the agent.
|
||||
func (k *kataAgent) handleBlockVolumes(c *Container) []*grpc.Storage {
|
||||
|
@ -369,6 +369,25 @@ func TestGenerateInterfacesAndRoutes(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestHandleEphemeralStorage(t *testing.T) {
|
||||
k := kataAgent{}
|
||||
var ociMounts []specs.Mount
|
||||
mountSource := "/tmp/mountPoint"
|
||||
|
||||
mount := specs.Mount{
|
||||
Type: kataEphemeralDevType,
|
||||
Source: mountSource,
|
||||
}
|
||||
|
||||
ociMounts = append(ociMounts, mount)
|
||||
epheStorages := k.handleEphemeralStorage(ociMounts)
|
||||
|
||||
epheMountPoint := epheStorages[0].GetMountPoint()
|
||||
expected := filepath.Join(ephemeralPath, filepath.Base(mountSource))
|
||||
assert.Equal(t, epheMountPoint, expected,
|
||||
"Ephemeral mount point didn't match: got %s, expecting %s", epheMountPoint, expected)
|
||||
}
|
||||
|
||||
func TestAppendDevicesEmptyContainerDeviceList(t *testing.T) {
|
||||
k := kataAgent{}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user