-
Notifications
You must be signed in to change notification settings - Fork 657
fix: allow containers to start using a large numbers of ports #4290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Because of my modifications, CI fails. |
Why are we not storing the range itself in the label? |
Hi, @apostasie Thanks for commnets!
I also think of a way to keep the range of ports in the label, but the following edge case would violate the upper limit of the number of labels. nerdctl run -p 127.0.0.1:32000:32000 -p 127.0.0.2:32001:32001 ~ -p 127.0.0.254:32253:32253 nginx Considering these cases, I think that when the port mapping information is given to the Label, it would violate the upper limit, so I implemented the way of this PR so that the port mapping information is not retained in the Label. When nerdctl compose up is executed, the ports specified in compose.yaml are expanded and executed by the following function: The ports are expanded and executed as |
02db289
to
c6e55d1
Compare
@AkihiroSuda so, this PR does move some of the network configuration information from labels (or annotations) to the filesystem. Future work to support per-network IP assignment (and options) will require significant re-jiggle of other annotations ( That overall does beg the question: should we stop using labels/annotations to store network configuration altogether, and just use a filesystem store for that instead? Answer to this question should inform whether we should consider expanding the scope of this PR a little bit to come up with a generic net-config-store that would in the future accommodate for other changes and additions ^. |
👍 We have to keep existing containers functional, though, if we are going to merge this in v2.1.x. |
Thanks for comments !!! I understand that it is acceptable to implement a policy of storing port mapping information in a local file. |
854dce9
to
16ddd16
Compare
Suppose we have a compose.yaml that allocates a large numbers of ports as follows. ``` > cat compose.yaml services: svc0: image: alpine command: "sleep infinity" ports: - '32000-32060:32000-32060' ``` When we run `nerdctl compose up -d` using this compose.yaml, we will get the following error. ``` FATA[0000] create container failed validation: containers.Labels: label key and value length (4711 bytes) greater than maximum size (4096 bytes), key: nerdctl/ports: invalid argument FATA[0000] error while creating container haytok-svc0-1: error while creating container haytok-svc0-1: exit status 1 ``` This issue is reported in the following issue. - containerd#4027 This issue is considered to be the same as the one with errors when trying to perform many port mappings, such as `nerdctl run -p 80:80 -p 81:81 ~ -p 1000:1000 ...` The current implementation is processing to create a container with the information specified in -p to the label. And as can be seen from the error message, as the number of ports to be port mapped increases, the creation of the container fails because it violates the limit of the maximum number of bytes on the containerd side that can be allocated for a label. Therefore, this PR modifies the container creation process so that containers can be launched without having to assign the information specified in the -p option to the labels. Specifically, port mapping information is stored in the following path, and when port mapping information is required, it is retrieved from this file. ``` <DATAROOT>/<ADDRHASH>/containers/<NAMESPACE>/<CID>/network-config.json ``` Signed-off-by: Hayato Kiwata <[email protected]>
Could you review when you have time ? 🙏 |
@@ -57,9 +57,6 @@ const ( | |||
// Currently, the length of the slice must be 1. | |||
Networks = Prefix + "networks" | |||
|
|||
// Ports is a JSON-marshalled string of []cni.PortMapping . | |||
Ports = Prefix + "ports" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change seems to break ports of containers created with an existing version of nerdctl ?
Then probably we should postpone this to v2.2.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for comments!!!
This change is not backward compatible, so these backward incompatible changes should be postponed until the update from 2.1
to 2.2
.
If so, is it okay to leave this PR open for now until the release of 2.2
approaches?
I'll rebase as necessary and ask you to review this PR when the release of 2.2
approaches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please.
There should be also a human-friendly warning message when an incompatible container exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add handling for cases where there are containers that are not backward compatible (e.g., when containers created using the -p option are already exist).
@@ -366,8 +365,8 @@ func TestRunWithInvalidPortThenCleanUp(t *testing.T) { | |||
}, | |||
Expected: func(data test.Data, helpers test.Helpers) *test.Expected { | |||
return &test.Expected{ | |||
ExitCode: 1, | |||
Errors: []error{errdefs.ErrInvalidArgument}, | |||
ExitCode: 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, is this test now working for both nerdctl and docker?
Should we lift the requirement?
@@ -892,12 +892,6 @@ func NetworkOptionsFromSpec(spec *specs.Spec) (types.NetworkOptions, error) { | |||
} | |||
opts.NetworkSlice = networks | |||
|
|||
if portsJSON := spec.Annotations[labels.Ports]; portsJSON != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PortMappings no longer set here?
if err != nil { | ||
return err | ||
} | ||
if _, err := os.Stat(loc); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ns.SafeStore.Exists()
instead of using os.Stat.
Also, do not ignore errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And move ns.SafeStore.Exists()
inside the locked section.
What if we make this change backward compatible? eg: func LoadPortMappings(dataStore, namespace, id string) ([]cni.PortMapping, error) {
// if there is no port information from NetworkStore, look into the labels |
@haytok a few comments above - also I think we should make this backward compatible (at least for reading the ports from the labels if they are there). |
Hi @apostasie Thanks for commens!!! I hadn't considered backward compatibility at all, so I'll update based on your advices to make backward compatible. |
Suppose we have a compose.yaml that allocates a large numbers of ports as follows.
When we run
nerdctl compose up -d
using this compose.yaml, we will get the following error.This issue is reported in the following issue.
This issue is considered to be the same as the one with errors when trying to perform many port mappings, such as
nerdctl run -p 80:80 -p 81:81 ~ -p 1000:1000 ...
The current implementation is processing to create a container with the information specified in
-p
to the label.And as can be seen from the error message, as the number of ports to be port mapped increases, the creation of the container fails because it violates the limit of the maximum number of bytes on the containerd side that can be allocated for a label.
Therefore, this PR modifies the container creation process so that containers can be launched without having to assign the information specified in the
-p
option to the labels.Specifically, port mapping information is stored in the following path, and when port mapping information is required, it is retrieved from this file.