fix data inconsistent when runc update in systemd driven cgroup v1

Signed-off-by: lifubang <lifubang@acmcoder.com>
This commit is contained in:
lifubang 2020-04-23 19:32:57 +08:00
parent 7682a2b2a5
commit 1d4ccc8e0c
1 changed files with 69 additions and 48 deletions

View File

@ -63,6 +63,59 @@ var legacySubsystems = subsystemSet{
&fs.NameGroup{GroupName: "name=systemd"}, &fs.NameGroup{GroupName: "name=systemd"},
} }
func genV1ResourcesProperties(c *configs.Cgroup) ([]systemdDbus.Property, error) {
var properties []systemdDbus.Property
if c.Resources.Memory != 0 {
properties = append(properties,
newProp("MemoryLimit", uint64(c.Resources.Memory)))
}
if c.Resources.CpuShares != 0 {
properties = append(properties,
newProp("CPUShares", c.Resources.CpuShares))
}
// cpu.cfs_quota_us and cpu.cfs_period_us are controlled by systemd.
if c.Resources.CpuQuota != 0 && c.Resources.CpuPeriod != 0 {
// corresponds to USEC_INFINITY in systemd
// if USEC_INFINITY is provided, CPUQuota is left unbound by systemd
// always setting a property value ensures we can apply a quota and remove it later
cpuQuotaPerSecUSec := uint64(math.MaxUint64)
if c.Resources.CpuQuota > 0 {
// systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota
// (integer percentage of CPU) internally. This means that if a fractional percent of
// CPU is indicated by Resources.CpuQuota, we need to round up to the nearest
// 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect.
cpuQuotaPerSecUSec = uint64(c.Resources.CpuQuota*1000000) / c.Resources.CpuPeriod
if cpuQuotaPerSecUSec%10000 != 0 {
cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000
}
}
properties = append(properties,
newProp("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec))
}
if c.Resources.BlkioWeight != 0 {
properties = append(properties,
newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight)))
}
if c.Resources.PidsLimit > 0 {
properties = append(properties,
newProp("TasksAccounting", true),
newProp("TasksMax", uint64(c.Resources.PidsLimit)))
}
// We have to set kernel memory here, as we can't change it once
// processes have been attached to the cgroup.
if c.Resources.KernelMemory != 0 {
if err := setKernelMemory(c); err != nil {
return nil, err
}
}
return properties, nil
}
func (m *LegacyManager) Apply(pid int) error { func (m *LegacyManager) Apply(pid int) error {
var ( var (
c = m.Cgroups c = m.Cgroups
@ -124,55 +177,11 @@ func (m *LegacyManager) Apply(pid int) error {
properties = append(properties, properties = append(properties,
newProp("DefaultDependencies", false)) newProp("DefaultDependencies", false))
if c.Resources.Memory != 0 { resourcesProperties, err := genV1ResourcesProperties(c)
properties = append(properties, if err != nil {
newProp("MemoryLimit", uint64(c.Resources.Memory)))
}
if c.Resources.CpuShares != 0 {
properties = append(properties,
newProp("CPUShares", c.Resources.CpuShares))
}
// cpu.cfs_quota_us and cpu.cfs_period_us are controlled by systemd.
if c.Resources.CpuQuota != 0 && c.Resources.CpuPeriod != 0 {
// corresponds to USEC_INFINITY in systemd
// if USEC_INFINITY is provided, CPUQuota is left unbound by systemd
// always setting a property value ensures we can apply a quota and remove it later
cpuQuotaPerSecUSec := uint64(math.MaxUint64)
if c.Resources.CpuQuota > 0 {
// systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota
// (integer percentage of CPU) internally. This means that if a fractional percent of
// CPU is indicated by Resources.CpuQuota, we need to round up to the nearest
// 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect.
cpuQuotaPerSecUSec = uint64(c.Resources.CpuQuota*1000000) / c.Resources.CpuPeriod
if cpuQuotaPerSecUSec%10000 != 0 {
cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000
}
}
properties = append(properties,
newProp("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec))
}
if c.Resources.BlkioWeight != 0 {
properties = append(properties,
newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight)))
}
if c.Resources.PidsLimit > 0 {
properties = append(properties,
newProp("TasksAccounting", true),
newProp("TasksMax", uint64(c.Resources.PidsLimit)))
}
// We have to set kernel memory here, as we can't change it once
// processes have been attached to the cgroup.
if c.Resources.KernelMemory != 0 {
if err := setKernelMemory(c); err != nil {
return err return err
} }
} properties = append(properties, resourcesProperties...)
properties = append(properties, c.SystemdProps...) properties = append(properties, c.SystemdProps...)
dbusConnection, err := getDbusConnection() dbusConnection, err := getDbusConnection()
@ -376,6 +385,18 @@ func (m *LegacyManager) Set(container *configs.Config) error {
if m.Cgroups.Paths != nil { if m.Cgroups.Paths != nil {
return nil return nil
} }
properties, err := genV1ResourcesProperties(container.Cgroups)
if err != nil {
return err
}
dbusConnection, err := getDbusConnection()
if err != nil {
return err
}
if err := dbusConnection.SetUnitProperties(getUnitName(container.Cgroups), true, properties...); err != nil {
return err
}
for _, sys := range legacySubsystems { for _, sys := range legacySubsystems {
// Get the subsystem path, but don't error out for not found cgroups. // Get the subsystem path, but don't error out for not found cgroups.
path, err := getSubsystemPath(container.Cgroups, sys.Name()) path, err := getSubsystemPath(container.Cgroups, sys.Name())