Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions completions/bash/crio
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ h
--image-volumes
--infra-ctr-cpuset
--insecure-registry
--irqbalance-config-file
--listen
--log
--log-dir
Expand Down
1 change: 1 addition & 0 deletions completions/fish/crio.fish
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ complete -c crio -n '__fish_crio_no_subcommand' -f -l insecure-registry -r -d 'E
be enabled for testing purposes**. For increased security, users should add
their CA to their system\'s list of trusted CAs instead of using
\'--insecure-registry\'.'
complete -c crio -n '__fish_crio_no_subcommand' -f -l irqbalance-config-file -r -d 'The irqbalance service config file which is used by CRI-O.'
complete -c crio -n '__fish_crio_no_subcommand' -l listen -r -d 'Path to the CRI-O socket'
complete -c crio -n '__fish_crio_no_subcommand' -l log -r -d 'Set the log file path where internal debug information is written'
complete -c crio -n '__fish_crio_no_subcommand' -l log-dir -r -d 'Default log directory where all logs will go unless directly specified by the kubelet'
Expand Down
2 changes: 1 addition & 1 deletion completions/zsh/_crio
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ it later with **--config**. Global options will modify the output.' 'version:dis
_describe 'commands' cmds

local -a opts
opts=('--additional-devices' '--apparmor-profile' '--big-files-temporary-dir' '--bind-mount-prefix' '--cgroup-manager' '--cni-config-dir' '--cni-default-network' '--cni-plugin-dir' '--config' '--config-dir' '--conmon' '--conmon-cgroup' '--conmon-env' '--container-attach-socket-dir' '--container-exits-dir' '--ctr-stop-timeout' '--decryption-keys-path' '--default-capabilities' '--default-env' '--default-mounts-file' '--default-runtime' '--default-sysctls' '--default-transport' '--default-ulimits' '--drop-infra-ctr' '--enable-metrics' '--gid-mappings' '--global-auth-file' '--grpc-max-recv-msg-size' '--grpc-max-send-msg-size' '--hooks-dir' '--image-volumes' '--infra-ctr-cpuset' '--insecure-registry' '--listen' '--log' '--log-dir' '--log-filter' '--log-format' '--log-journald' '--log-level' '--log-size-max' '--metrics-port' '--metrics-socket' '--namespaces-dir' '--no-pivot' '--pause-command' '--pause-image' '--pause-image-auth-file' '--pids-limit' '--pinns-path' '--profile' '--profile-port' '--read-only' '--registries-conf' '--registry' '--root' '--runroot' '--runtimes' '--seccomp-profile' '--seccomp-use-default-when-empty' '--selinux' '--separate-pull-cgroup' '--signature-policy' '--storage-driver' '--storage-opt' '--stream-address' '--stream-enable-tls' '--stream-port' '--stream-tls-ca' '--stream-tls-cert' '--stream-tls-key' '--uid-mappings' '--version-file' '--version-file-persist' '--help' '--version')
opts=('--additional-devices' '--apparmor-profile' '--big-files-temporary-dir' '--bind-mount-prefix' '--cgroup-manager' '--cni-config-dir' '--cni-default-network' '--cni-plugin-dir' '--config' '--config-dir' '--conmon' '--conmon-cgroup' '--conmon-env' '--container-attach-socket-dir' '--container-exits-dir' '--ctr-stop-timeout' '--decryption-keys-path' '--default-capabilities' '--default-env' '--default-mounts-file' '--default-runtime' '--default-sysctls' '--default-transport' '--default-ulimits' '--drop-infra-ctr' '--enable-metrics' '--gid-mappings' '--global-auth-file' '--grpc-max-recv-msg-size' '--grpc-max-send-msg-size' '--hooks-dir' '--image-volumes' '--infra-ctr-cpuset' '--insecure-registry' '--irqbalance-config-file' '--listen' '--log' '--log-dir' '--log-filter' '--log-format' '--log-journald' '--log-level' '--log-size-max' '--metrics-port' '--metrics-socket' '--namespaces-dir' '--no-pivot' '--pause-command' '--pause-image' '--pause-image-auth-file' '--pids-limit' '--pinns-path' '--profile' '--profile-port' '--read-only' '--registries-conf' '--registry' '--root' '--runroot' '--runtimes' '--seccomp-profile' '--seccomp-use-default-when-empty' '--selinux' '--separate-pull-cgroup' '--signature-policy' '--storage-driver' '--storage-opt' '--stream-address' '--stream-enable-tls' '--stream-port' '--stream-tls-ca' '--stream-tls-cert' '--stream-tls-key' '--uid-mappings' '--version-file' '--version-file-persist' '--help' '--version')
_describe 'global options' opts

return
Expand Down
3 changes: 3 additions & 0 deletions docs/crio.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ crio
[--image-volumes]=[value]
[--infra-ctr-cpuset]=[value]
[--insecure-registry]=[value]
[--irqbalance-config-file]=[value]
[--listen]=[value]
[--log-dir]=[value]
[--log-filter]=[value]
Expand Down Expand Up @@ -224,6 +225,8 @@ crio [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
their CA to their system's list of trusted CAs instead of using
'--insecure-registry'. (default: [])

**--irqbalance-config-file**="": The irqbalance service config file which is used by CRI-O. (default: /etc/sysconfig/irqbalance)

**--listen**="": Path to the CRI-O socket (default: /var/run/crio/crio.sock)

**--log**="": Set the log file path where internal debug information is written
Expand Down
4 changes: 4 additions & 0 deletions docs/crio.conf.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ the container runtime configuration.
**apparmor_profile**=""
Used to change the name of the default AppArmor profile of CRI-O. The default profile name is "crio-default".

**irqbalance_config_file**="/etc/sysconfig/irqbalance"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a blurb about where this file should be for which distro (only for the most popular: ubuntu/centos, maybe debian/rhel if they differ at all)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! done, I was able to confirm the file locations only in centos/suse and ubuntu platforms. so added it only for those cases.

Used to change irqbalance service config file which is used by CRI-O.
For CentOS/SUSE, this file is located at /etc/sysconfig/irqbalance. For Ubuntu, this file is located at /etc/default/irqbalance.

**cgroup_manager**="systemd"
Cgroup management implementation used for the runtime.

Expand Down
8 changes: 8 additions & 0 deletions internal/criocli/criocli.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ func mergeConfig(config *libconfig.Config, ctx *cli.Context) error {
if ctx.IsSet("apparmor-profile") {
config.ApparmorProfile = ctx.String("apparmor-profile")
}
if ctx.IsSet("irqbalance-config-file") {
config.IrqBalanceConfigFile = ctx.String("irqbalance-config-file")
}
if ctx.IsSet("cgroup-manager") {
config.CgroupManagerName = ctx.String("cgroup-manager")
}
Expand Down Expand Up @@ -524,6 +527,11 @@ func getCrioFlags(defConf *libconfig.Config) []cli.Flag {
Value: defConf.ApparmorProfile,
EnvVars: []string{"CONTAINER_APPARMOR_PROFILE"},
},
&cli.StringFlag{
Name: "irqbalance-config-file",
Usage: "The irqbalance service config file which is used by CRI-O.",
Value: defConf.IrqBalanceConfigFile,
},
&cli.BoolFlag{
Name: "selinux",
Usage: fmt.Sprintf("Enable selinux support (default: %t)", defConf.SELinux),
Expand Down
115 changes: 97 additions & 18 deletions internal/runtimehandlerhooks/high_performance_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,25 @@ import (
const (
// HighPerformance contains the high-performance runtime handler name
HighPerformance = "high-performance"
// IrqBannedCPUConfigFile contains the original banned cpu mask configuration
IrqBannedCPUConfigFile = "/etc/sysconfig/orig_irq_banned_cpus"
// IrqSmpAffinityProcFile contains the default smp affinity mask configuration
IrqSmpAffinityProcFile = "/proc/irq/default_smp_affinity"
)

const (
annotationTrue = "true"
annotationDisable = "disable"
schedDomainDir = "/proc/sys/kernel/sched_domain"
irqSmpAffinityProcFile = "/proc/irq/default_smp_affinity"
cgroupMountPoint = "/sys/fs/cgroup"
annotationTrue = "true"
annotationDisable = "disable"
schedDomainDir = "/proc/sys/kernel/sched_domain"
cgroupMountPoint = "/sys/fs/cgroup"
irqBalanceBannedCpus = "IRQBALANCE_BANNED_CPUS"
irqBalancedName = "irqbalance"
)

// HighPerformanceHooks used to run additional hooks that will configure a system for the latency sensitive workloads
type HighPerformanceHooks struct{}
type HighPerformanceHooks struct {
irqBalanceConfigFile string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why have this file as a member of the Hooks, when the other file locations are hardcoded?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@haircommander This file location is platform dependent. For example, in Ubuntu, the config file is /etc/default/irqbalance. Hence making it to configure from a RuntimeConfig property. Can you check it now ?

}

func (h *HighPerformanceHooks) PreStart(ctx context.Context, c *oci.Container, s *sandbox.Sandbox) error {
log.Infof(ctx, "Run %q runtime handler pre-start hook for the container %q", HighPerformance, c.ID())
Expand Down Expand Up @@ -66,7 +73,7 @@ func (h *HighPerformanceHooks) PreStart(ctx context.Context, c *oci.Container, s
// disable the IRQ smp load balancing for the container CPUs
if shouldIRQLoadBalancingBeDisabled(s.Annotations()) {
log.Infof(ctx, "Disable irq smp balancing for container %q", c.ID())
if err := setIRQLoadBalancing(c, false, irqSmpAffinityProcFile); err != nil {
if err := setIRQLoadBalancing(c, false, IrqSmpAffinityProcFile, h.irqBalanceConfigFile); err != nil {
return errors.Wrap(err, "set IRQ load balancing")
}
}
Expand Down Expand Up @@ -111,7 +118,7 @@ func (h *HighPerformanceHooks) PreStop(ctx context.Context, c *oci.Container, s

// enable the IRQ smp balancing for the container CPUs
if shouldIRQLoadBalancingBeDisabled(s.Annotations()) {
if err := setIRQLoadBalancing(c, true, irqSmpAffinityProcFile); err != nil {
if err := setIRQLoadBalancing(c, true, IrqSmpAffinityProcFile, h.irqBalanceConfigFile); err != nil {
return errors.Wrap(err, "set IRQ load balancing")
}
}
Expand Down Expand Up @@ -219,7 +226,7 @@ func setCPUSLoadBalancing(c *oci.Container, enable bool, schedDomainDir string)
return nil
}

func setIRQLoadBalancing(c *oci.Container, enable bool, irqSmpAffinityFile string) error {
func setIRQLoadBalancing(c *oci.Container, enable bool, irqSmpAffinityFile, irqBalanceConfigFile string) error {
lspec := c.Spec().Linux
if lspec == nil ||
lspec.Resources == nil ||
Expand All @@ -240,16 +247,32 @@ func setIRQLoadBalancing(c *oci.Container, enable bool, irqSmpAffinityFile strin
if err := ioutil.WriteFile(irqSmpAffinityFile, []byte(newIRQSMPSetting), 0o644); err != nil {
return err
}
if _, err := exec.LookPath("irqbalance"); err != nil {
// irqbalance is not installed, skip the rest; pod should still start, so return nil instead
logrus.Warnf("irqbalance binary not found: %v", err)
return nil

isIrqConfigExists := fileExists(irqBalanceConfigFile)

if isIrqConfigExists {
if err := updateIrqBalanceConfigFile(irqBalanceConfigFile, newIRQBalanceSetting); err != nil {
return err
}
}

if !isServiceEnabled(irqBalancedName) || !isIrqConfigExists {
if _, err := exec.LookPath(irqBalancedName); err != nil {
// irqbalance is not installed, skip the rest; pod should still start, so return nil instead
logrus.Warnf("irqbalance binary not found: %v", err)
return nil
}
// run irqbalance in daemon mode, so this won't cause delay
cmd := exec.Command(irqBalancedName, "--oneshot")
additionalEnv := irqBalanceBannedCpus + "=" + newIRQBalanceSetting
cmd.Env = append(os.Environ(), additionalEnv)
return cmd.Run()
}

if err := restartIrqBalanceService(); err != nil {
logrus.Warnf("irqbalance service restart failed: %v", err)
}
// run irqbalance in daemon mode, so this won't cause delay
cmd := exec.Command("irqbalance", "--oneshot")
additionalEnv := "IRQBALANCE_BANNED_CPUS=" + newIRQBalanceSetting
cmd.Env = append(os.Environ(), additionalEnv)
return cmd.Run()
return nil
}

func setCPUQuota(cpuMountPoint, parentDir string, c *oci.Container, enable bool) error {
Expand Down Expand Up @@ -311,3 +334,59 @@ func setCPUQuota(cpuMountPoint, parentDir string, c *oci.Container, enable bool)

return nil
}

// RestoreIrqBalanceConfig restores irqbalance service with original banned cpu mask settings
func RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSmpAffinityProcFile string) error {
content, err := ioutil.ReadFile(irqSmpAffinityProcFile)
if err != nil {
return err
}
current := strings.TrimSpace(string(content))
// remove ","; now each element is "0-9,a-f"
s := strings.ReplaceAll(current, ",", "")
currentMaskArray, err := mapHexCharToByte(s)
if err != nil {
return err
}
if !isAllBitSet(currentMaskArray) {
// not system reboot scenario, just return it.
return nil
}

bannedCPUMasks, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile)
if err != nil {
// Ignore returning err as given irqBalanceConfigFile may not exist.
return nil
}
if !fileExists(irqBannedCPUConfigFile) {
irqBannedCPUsConfig, err := os.Create(irqBannedCPUConfigFile)
if err != nil {
return err
}
defer irqBannedCPUsConfig.Close()
_, err = irqBannedCPUsConfig.WriteString(bannedCPUMasks)
if err != nil {
return err
}
return nil
}

content, err = ioutil.ReadFile(irqBannedCPUConfigFile)
if err != nil {
return err
}
origBannedCPUMasks := strings.TrimSpace(string(content))

if bannedCPUMasks == origBannedCPUMasks {
return nil
}
if err := updateIrqBalanceConfigFile(irqBalanceConfigFile, origBannedCPUMasks); err != nil {
return err
}
if isServiceEnabled(irqBalancedName) {
if err := restartIrqBalanceService(); err != nil {
logrus.Warnf("irqbalance service restart failed: %v", err)
}
}
return nil
}
131 changes: 128 additions & 3 deletions internal/runtimehandlerhooks/high_performance_hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var _ = Describe("high_performance_hooks", func() {
false, "", "", time.Now(), "")
Expect(err).To(BeNil())

var flags string
var flags, bannedCPUFlags string

BeforeEach(func() {
err := os.MkdirAll(fixturesDir, os.ModePerm)
Expand Down Expand Up @@ -107,10 +107,11 @@ var _ = Describe("high_performance_hooks", func() {
})
})

Describe("setIRQLoadBalancing", func() {
Describe("setIRQLoadBalancingUsingDaemonCommand", func() {
irqSmpAffinityFile := filepath.Join(fixturesDir, "irq_smp_affinity")
irqBalanceConfigFile := filepath.Join(fixturesDir, "irqbalance")
verifySetIRQLoadBalancing := func(enabled bool, expected string) {
err := setIRQLoadBalancing(container, enabled, irqSmpAffinityFile)
err := setIRQLoadBalancing(container, enabled, irqSmpAffinityFile, irqBalanceConfigFile)
Expect(err).To(BeNil())

content, err := ioutil.ReadFile(irqSmpAffinityFile)
Expand Down Expand Up @@ -159,6 +160,130 @@ var _ = Describe("high_performance_hooks", func() {
})
})

Describe("setIRQLoadBalancingUsingServiceRestart", func() {
irqSmpAffinityFile := filepath.Join(fixturesDir, "irq_smp_affinity")
irqBalanceConfigFile := filepath.Join(fixturesDir, "irqbalance")
verifySetIRQLoadBalancing := func(enabled bool, expectedSmp, expectedBan string) {
err = setIRQLoadBalancing(container, enabled, irqSmpAffinityFile, irqBalanceConfigFile)
Expect(err).To(BeNil())

content, err := ioutil.ReadFile(irqSmpAffinityFile)
Expect(err).To(BeNil())

Expect(strings.Trim(string(content), "\n")).To(Equal(expectedSmp))

bannedCPUs, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile)
Expect(err).To(BeNil())

Expect(bannedCPUs).To(Equal(expectedBan))
}

JustBeforeEach(func() {
// set irqbalanace config file with no banned cpus
err = ioutil.WriteFile(irqBalanceConfigFile, []byte(""), 0o644)
Expect(err).To(BeNil())
err = updateIrqBalanceConfigFile(irqBalanceConfigFile, bannedCPUFlags)
Expect(err).To(BeNil())
bannedCPUs, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile)
Expect(err).To(BeNil())
Expect(bannedCPUs).To(Equal(bannedCPUFlags))
// set container CPUs
container.SetSpec(
&specs.Spec{
Linux: &specs.Linux{
Resources: &specs.LinuxResources{
CPU: &specs.LinuxCPU{
Cpus: "4,5",
},
},
},
},
)

// create tests affinity file
err = ioutil.WriteFile(irqSmpAffinityFile, []byte(flags), 0o644)
Expect(err).To(BeNil())
})

Context("with enabled equals to true", func() {
BeforeEach(func() {
flags = "00000000,00003003"
bannedCPUFlags = "ffffffff,ffffcffc"
})

It("should set the irq bit mask", func() {
verifySetIRQLoadBalancing(true, "00000000,00003033", "ffffffff,ffffcfcc")
})
})

Context("with enabled equals to false", func() {
BeforeEach(func() {
flags = "00000000,00003033"
bannedCPUFlags = "ffffffff,ffffcfcc"
})

It("should clear the irq bit mask", func() {
verifySetIRQLoadBalancing(false, "00000000,00003003", "ffffffff,ffffcffc")
})
})
})

Describe("restoreIrqBalanceConfig", func() {
irqSmpAffinityFile := filepath.Join(fixturesDir, "irq_smp_affinity")
irqBalanceConfigFile := filepath.Join(fixturesDir, "irqbalance")
irqBannedCPUConfigFile := filepath.Join(fixturesDir, "orig_irq_banned_cpus")
verifyRestoreIrqBalanceConfig := func(expectedOrigBannedCPUs, expectedBannedCPUs string) {
err = RestoreIrqBalanceConfig(irqBalanceConfigFile, irqBannedCPUConfigFile, irqSmpAffinityFile)
Expect(err).To(BeNil())

content, err := ioutil.ReadFile(irqBannedCPUConfigFile)
Expect(err).To(BeNil())
Expect(strings.Trim(string(content), "\n")).To(Equal(expectedOrigBannedCPUs))

bannedCPUs, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile)
Expect(err).To(BeNil())
Expect(bannedCPUs).To(Equal(expectedBannedCPUs))
}

JustBeforeEach(func() {
// create tests affinity file
err = ioutil.WriteFile(irqSmpAffinityFile, []byte("ffffffff,ffffffff"), 0o644)
Expect(err).To(BeNil())
// set irqbalanace config file with banned cpus mask
err = ioutil.WriteFile(irqBalanceConfigFile, []byte(""), 0o644)
Expect(err).To(BeNil())
err = updateIrqBalanceConfigFile(irqBalanceConfigFile, "0000ffff,ffffcfcc")
Expect(err).To(BeNil())
bannedCPUs, err := retrieveIrqBannedCPUMasks(irqBalanceConfigFile)
Expect(err).To(BeNil())
Expect(bannedCPUs).To(Equal("0000ffff,ffffcfcc"))
})

Context("when banned cpu config file doesn't exist", func() {
BeforeEach(func() {
// ensure banned cpu config file doesn't exist
os.Remove(irqBannedCPUConfigFile)
})

It("should set banned cpu config file from irq balance config", func() {
verifyRestoreIrqBalanceConfig("0000ffff,ffffcfcc", "0000ffff,ffffcfcc")
})
})

Context("when banned cpu config file exists", func() {
BeforeEach(func() {
// create banned cpu config file
os.Remove(irqBannedCPUConfigFile)
err = ioutil.WriteFile(irqBannedCPUConfigFile, []byte("00000000,00000000"), 0o644)
Expect(err).To(BeNil())
})

It("should restore irq balance config with content from banned cpu config file", func() {
verifyRestoreIrqBalanceConfig("00000000,00000000", "00000000,00000000")
})
})
})

Describe("setCPUQuota", func() {
containerID := container.ID()
parent := "parent.slice"
Expand Down
Loading