8000 Expose the `--raw-port` flag in the run and run-prepared subcommands by squeed · Pull Request #3407 · rkt/rkt · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Feb 24, 2020. It is now read-only.

Conversation

squeed
Copy link
Contributor
@squeed squeed commented Nov 23, 2016

Fixes #2113

Copy link
Member
@lucab lucab left a comment

Choose a reason for hiding this comment

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

If possible, I'd like to avoid introducing an additional --raw-port option. It looks quite confusing in its current form.

// along with the flagStringList, used everywhere

// flagStringList implements the flag.Value interface to contain a set of strings
type flagStringList []string
Copy link
Member

Choose a reason for hiding this comment

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

These belong to rkt/cli_apps.go I guess.

Now, any traffic arriving on host's TCP port 8888 on any IP will be forwarded to the pod on port 80.


You can also forward a port that is not referenced at the app time with the `--raw-port` option. The syntax is Name, Protocol (`tcp` or `udp`), Pod port, Host IP (use 0.0.0.0 for all IPs), Host port.
Copy link
Member

Choose a reason for hiding this comment

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

"referenced in the app manifest" perhaps?

Copy link
Member

Choose a reason for hiding this comment

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

What is "Name" here and what is the user supposed to pick for it? Can we do better and just generate one for the user? Or ask the user to name them port-proto so we can automatically pick them up without a new option?

| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080` |
| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:<HOSTIP>:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080`. The HOSTIP is optional. |
| `--private-users` | `false` | `t 10000 rue` or `false` | Run within user namespaces |
| `--raw-port` | none | A port to forward from the host to the pod | Syntax: `--raw-port=name:proto:podPort:hostIP:hostPort`, e.g. `http:tcp:80:0.0.0.0:8080` |
Copy link
Member
@lucab lucab Nov 23, 2016

Choose a reason for hiding this comment

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

IMHO this looks quite ugly from a UX point of view.

@lucab lucab added this to the v1.21.0 milestone Nov 23, 2016
Copy link
Contributor
@jonboulle jonboulle left a comment

Choose a reason for hiding this comment

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

I must be losing my vision but I don't see CLI tests for this new flag... ;-)

| `--no-store` | `false` | `true` or `false` | Fetch images, ignoring the local store. See [image fetching behavior][img-fetch] |
| `--pod-manifest` | none | A path | The path to the pod manifest. If it's non-empty, then only `--net`, `--no-overlay` and `--interactive` will have effect. |
| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080` |
| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:<HOSTIP>:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080`. The HOSTIP is optional. |
Copy link
Contributor

Choose a reason for hiding this comment

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

use [:HOSTIP] to denote optionality

Copy link
Contributor

Choose a reason for hiding this comment

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

(also HOSTIP could do with a brief description)

Choose a reason for hiding this comment

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

Syntax should follow the OCI spec v1.0.1 and being adopted in other tools and documentation:

--port 80/tcp

| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080` |
| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:<HOSTIP>:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080`. The HOSTIP is optional. |
| `--private-users` | `false` | `true` or `false` | Run within user namespaces |
| `--raw-port` | none | A port to forward from the host to the pod | Syntax: `--raw-port=name:proto:podPort:hostIP:hostPort`, e.g. `http:tcp:80:0.0.0.0:8080` |
Copy link
Contributor

Choose a reason for hiding this comment

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

NAME:PROTO:PODPORT:HOSTIP:HOSTPORT as elsewhere

| `--no-store` | `false` | `true` or `false` | Fetch images, ignoring the local store. See [image fetching behavior][img-fetch]. |
| `--pod-manifest` | none | A path | The path to the pod manifest. If it's non-empty, then only `--net`, `--no-overlay` and `--interactive` will have effect. |
| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080`. |
| `--port` | none | A port name and number pair | Container port name to expose through host port number. Requires [contained network][contained]. Syntax: `--port=NAME:<HOSTIP>:HOSTPORT` The NAME is that given in the ACI. By convention, Docker containers' EXPOSEd ports are given a name formed from the port number, a hyphen, and the protocol, e.g., `80-tcp`, giving something like `--port=80-tcp:8080`. The HOSTIP is optional. |
Copy link
Contributor

Choose a reason for hiding this comment

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

As above. (Seems like we should have a shared section for the prepare/run options....)

// flagStringList implements the flag.Value interface to contain a set of strings
type flagStringList []string

func (dns *flagStringList) Set(s string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, s/dns/fsl/

// argument. This is need to permit to correctly handle
// multiple "IMAGE -- imageargs ---" options
cmdPrepare.Flags().SetInterspersed(false)
flagPorts = portList{}
Copy link
Contributor

Choose a reason for hiding this comment

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

seems like there could be a more logical location for this (separate from this interspersed operation at least)

@jonboulle
Copy link
Contributor

Sorry, my review was a little half-baked from yesterday before luca started his so some of his comments take precedence.

@squeed
Copy link
Contributor Author
squeed commented Nov 24, 2016

This was supposed to be a small PR, exposing the app sandbox flag to the run subcommand. However, I agree it could be better :-).

The current question is: Should we have some way of overloading the "port name" designator currently used in --port to specify an arbitrary port? Right now, you can only pass a value to --port that references something exposed by a manifest. Luca suggested this - and by doing so, we could remove a CLI flag at the loss of a bit of simplicity.

This is made extra silly by our current synthesis of ports exposed by Docker images, since they don't have names. So the port name is just tcp-80, for example. We could just always parse this. It's the simplest case from a UX perspective, and that's always a good thing.

@jonboulle
Copy link
Contributor
jonboulle commented Nov 24, 2016 via email

@squeed
Copy link
Contributor Author
squeed commented Nov 24, 2016

So, Dockerfiles have the EXPOSE <portnum> directive. We carry this over in to the appc manifest, but we require all ports to be named. So, we synthesize a name of tcp-80, for example, when converting from Docker/OCI.

Therefore you might do something like rkt run docker://nginx --port=tcp-80:8080. However, this will only work for ports declared by the applications.

However, the CRI specifies that port forwarding should be set up before any applications are added. So right now rkt app sandbox already supports the ability to map arbitrary pod and host ports. This is the --raw-port option, which is already merged. There is an enhancement assigned to me, though, for this kind of arbitrary port forwarding to be generally available.

So, we can either add --raw-port to rkt run or just parse --port=tcp-80 even when doesn't reference a EXPOSEd port. This PR does the former. @lucab wants the latter.

@jonboulle
Copy link
Contributor

Are there any cases in which parsing would result in undesired/unexpected behaviour? (I mean in non-parse-failure cases)

@squeed
Copy link
Contributor Author
squeed commented Nov 28, 2016

Not really.

I suppose if someone was relying on something tcp-80 to fail if the port wasn't EXPOSEd, then this wouldn't work. I can't think of a reasonable case for that.

@lucab
Copy link
Member
lucab commented Nov 28, 2016

The only other source of confusion I see is if some aci specifies a tcp-80 name for some other custom port (eg. pointing to UDP 53). But I'd honestly prefer to trade this off for a simpler CLI.

@jonboulle
Copy link
Contributor

SGTM

@lucab
Copy link
Member
lucab commented Nov 30, 2016

So are we in agreement that we should:

  • remove --raw-port from rkt-app
  • add the name parsing logic to --port

right?

@squeed
Copy link
Contributor Author
squeed commented Dec 8, 2016

This didn't quite make it in time for this release, bumping.

@squeed squeed modified the milestones: v1.22.0, v1.21.0 Dec 8, 2016
@euank
Copy link
Member
euank commented Dec 19, 2016

This issue looks like a perfect candidate for bikeshedding.

So, what we've got now is --port=NAME:[hostIp:]hostPort. Whatever we pick presumably needs to be backwards compatible with that.

The information missing from the above is: 1) the container port number, 2) the protocol.

That information right now is resolved via the name having already been associated with that info, but the point is to remove that requirement.

The current suggestion is to make the name be acceptable as either a name of a port defined within the image, or as $port-$protocol which will be parsed out.

We have quite a few possible colours we can paint this particular bikeshed instead though, and I'd prefer taking a look at what the colours are before picking the above.

CSV

We have various options which are comma-separated key-value pairs. We could introduce that to --port, but in a backwards compatible way. Effectively, our code could be "if contains comma, newParsing, else olldParsing".

This would allow us to use something like: --port containerPort=80,hostPort=80,proto=udp,bindIP=0.0.0.0 (with obvious defaulting and optional value-ing).

Heuristically parsing

Currently, by convention, docker2aci leaves ports of the form $port-$protocol annotated. We could formalize that convention further such that it is interpreted at the command line too. This is adding new meaning to the "name" field which used to be arbitrary. This is the suggestion made above.

I think this has the downside of being le 6854 ss obvious (more "magic"). It's also easy for a user to typo (e.g. tcp-80 instead of 80-tcp).

The upside is that backwards compatibility is free.

More colons

We could extend the existing --port=NAME:[hostIp:]hostPort flag to have more possible fields. The most obvious extension would be to move it to name:[proto:][containerPort:][hostIp:]hostPort. Parsing which of each is present is a little tricky, but is very possible! Something might now look like --port myport:80:80 (protocol defaulted to tcp, hostIp defaulted as it does now).
A full set of options would look like --port myport:tcp:8080:127.0.0.1:80

This has the upside of being the most consistent with the current option of --port, and also has free backwards compatibility.


I think painting more colons onto our bikeshed is probably a better option that going with a heuristically coloured one. The CSV colour also looks quite nice to me, though I'm not really a fan of the amount of typing required for the --volume options due to them being CSV, so maybe we should shy away from that.

@squeed
Copy link
Contributor Author
squeed commented Dec 20, 2016

So, right now we have:

  • 1 colon: name:hostport
  • 2 colons: name:hostip:hostport

If we go according to @euank's suggestion, then we have the additional valid cases:

  • 3 colons: name:proto:podPort:hostPort
  • 4 colons: name:proto:podPort:hostIP:hostPort <-- This is currently what rkt app sandbox requires

After some thought, I want to just get rid of name. It doesn't serve a purpose outside of pod manifests, and we're lessening emphasis on them. Instead, it should be called portSpec and it either references a named exposed port, or is parsed in the proto-num format. That way we don't add any additional parsing cases.

@euank
Copy link
Member
euank commented Dec 20, 2016

@squeed there are more valid cases than that as well:

2 colons can be any of:

  1. name:hostip:hostport
  2. name:proto:hostport
  3. name:containerport:hostport

proto, ips, and ports can all be distinguished from each other, so I don't think there are any ambiguous cases.

@squeed
Copy link
Contributor Author
squeed commented Dec 20, 2016

Hence my desire to keep the proto-port convention :-).
Also, never feel badly about bikeshedding UX. Especially where we can't really change it after the fact. Usability is important!

@jonboulle
Copy link
Contributor

I'm confused about the end of this discussion. Do we have a decision?

@squeed
Copy link
Contributor Author
squeed commented Dec 21, 2016

Only if @euank can convince me not to parse "tcp-80" in all cases :-).

@euank
Copy link
Member
euank commented Dec 21, 2016

@squeed I left my reasoning why I don't like it.

I personally wouldn't have much problem typing --port http:80:80 (with that being the most common number of parts for a typical user I think). I slightly prefer that to the overloading done by --port 80-tcp:80

Being able to omit tcp and have it assumed is nice.
I agree that it would be nice if name were optional, and it's possible we could technically accomplish that.

With that, I have a final option for this bikeshed

Optional Name

--port [proto:][containerPort:][hostIp:]hostPort with the following assumption:

  1. The name of a port specified in an image will not generally be "udp", "tcp", or all numeric

The logic would be something like: "if the first part would be valid as a port name, interpret it as the current --port flag behaviour, otherwise the above".

Pros:

  • Allows the shortest possible argument of --port 80:80
  • Allows omitting "tcp" (vs '80-tcp')
  • Removes the 'name' thing which would be vestigial in this use-case

Cons:

  • Reverse of the docker ordering for consistency with previous --port behavior (e.g. containerPort:hostPort vs hostPort:containerPort) .. we could reverse this though
  • Totally explodes if someone has an image with a port named "tcp" or "80" or whatever.
  • More complicated code by a little bit

@lucab lucab modified the milestones: v1.23.0, v1.22.0 Jan 5, 2017
@s-urbaniak
Copy link
6854 Contributor

@squeed @euank ping re: the final state of the discussion :-) I am bumping this to the next release.

@s-urbaniak s-urbaniak added this to the v1.24.0 milestone Jan 19, 2017
@trusch
Copy link
Contributor
trusch commented May 30, 2017

Just my two cents:

Another option would be to introduce an "--expose [name=]http,proto=tcp,port=80" like option on app level. This would simply patch the image manifest (or the pod-manifest, not sure about the details). The --port option could then use the newly defined port-identifier. This would be similar to the --mount option which is used if the aci doesnt provide mount points.

I think this would be more easy to understand, and you can memorize the syntax better than with a hundred optional positional arguments.

Pros:

  • no change to "--port" parsing
  • -> 100% backward compatible
  • same approach as mounting volumes
  • proto can be omitted

Cons:

  • New command line option
  • no --port 80:80 possible

@ghost
Copy link
ghost commented May 30, 2017

Can one of the admins verify this patch?

@trusch
Copy link
Contributor
trusch commented May 30, 2017

(github.com/appc/spec/schema/types).PortFromString() is already there and could do the parsing.

Then I would simply add that port to the app in the pod-manifest in the end of the run call right before stage0.Run() is called (in rkt/run.go:404)

trusch added a commit to trusch/rkt that referenced this pull request May 31, 2017
This allows us to specify exposed ports at runtime in favor of patching the image manifests.
A typical call will look like this:

rkt run \
  --port shell:11111 \
  trusch.io/alpine \
    --expose shell,port=12345,protocol=tcp \
    --exec nc -- -lk -p 12345 -e /bin/sh

This fixes issue rkt#2113 and is conflicting with PR rkt#3407
@squeed squeed removed their assignment Oct 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

run: new option to add a port at run-time (--port= needs a port in the ACI)
7 participants
0