operator-framework / operator-framework/ansible-operator-plugins

Use runtime.GOMAXPROCS(0) instead of runtime.NumCPU() to set --max-concurrent-reconciles default

Open Beginner friendly
#222 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
12
Forks
33
PR merge metrics
No merged PRs in 30d

Description

Bug Report

What did you do?

Ansible operator plugin should consider using runtime.GOMAXPROCS(0) to set --max-concurrent-reconciles instead of runtime.NumCPU() in https://github.com/operator-framework/ansible-operator-plugins/blob/main/internal/ansible/flags/flag.go#L109.

What did you expect to see?

--max-concurrent-reconciles should take into account the pod's CPU resource limits so as to not start too many simultaneous playbooks.

What did you see instead? Under which circumstances?

runtime.NumCPU() will return the number of logical CPUs usable by the current process, which does not seem to be cgroup-aware. This means that --max-concurrent-reconciles can be set to a large number on OpenShift nodes with a large number of CPUs. This can cause the Ansible operator to start up too many playbooks simultaneously, eating up memory and leading to the pod being OOM killed.

On an OpenShift compute node with 128 CPUs, the operator set the default --max-concurrent-reconciles to 128. This particular environment had over 30 AnsibleAutomationPlatformBackup resources, which meant the operator tried to start over 30 simultaneous playbooks. This used up quite a bit of memory, causing the pod to exceed the 4000Mi resource limit which lead to it being OOM killed.

The pod that was OOM killed did have CPU resource limits set, but the operator did not seem to take those into account when determining the maximum number of concurrent reconciles.

resources:        
  limits:         
    cpu: "2"      
    memory: 4000Mi
  requests:       
    cpu: 10m      
    memory: 256Mi 
Environment

Kubernetes cluster type:

OpenShift

This behavior was observed with Ansible Automation Platform operator 2.5 using Go 1.21.13.

ansible-operator version: "v1.31.0-ocp", commit: "731dca792e1343af155b82bc3c34a5800ee863af", kubernetes version: "v1.26.0", go version: "go1.21.13 (Red Hat 1.21.13-3.module+el8.10.0+22345+acdd8d0e) X:strictfipsruntime", GOOS: "linux", GOARCH: "amd64"
Possible Solution

Switch to using runtime.GOMAXPROCS(0) which seems to be cgroup-aware since Go 1.25.

For versions less than 1.25, using runtime.GOMAXPROCS(0) seems to return the same value as runtime.NumCPU().

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in internal/ansible/flags/flag.go around line 109, where the default for --max-concurrent-reconciles is set. Verify how the current runtime.NumCPU() value is used, then confirm the default uses the proposed runtime behavior so pod CPU limits are reflected and excessive concurrent playbooks are avoided.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
devops
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.