mirror of
https://github.com/containers/podman.git
synced 2025-06-08 00:00:51 +08:00
play kube add support for multiple networks
Allow the same --network options for play kube as for podman run/create. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
@ -69,7 +69,7 @@ func init() {
|
|||||||
_ = kubeCmd.RegisterFlagCompletionFunc(staticMACFlagName, completion.AutocompleteNone)
|
_ = kubeCmd.RegisterFlagCompletionFunc(staticMACFlagName, completion.AutocompleteNone)
|
||||||
|
|
||||||
networkFlagName := "network"
|
networkFlagName := "network"
|
||||||
flags.StringVar(&kubeOptions.Network, networkFlagName, "", "Connect pod to CNI network(s)")
|
flags.StringArrayVar(&kubeOptions.Networks, networkFlagName, nil, "Connect pod to network(s) or network mode")
|
||||||
_ = kubeCmd.RegisterFlagCompletionFunc(networkFlagName, common.AutocompleteNetworkFlag)
|
_ = kubeCmd.RegisterFlagCompletionFunc(networkFlagName, common.AutocompleteNetworkFlag)
|
||||||
|
|
||||||
staticIPFlagName := "ip"
|
staticIPFlagName := "ip"
|
||||||
|
@ -142,6 +142,7 @@ removed. Any volumes created are left intact.
|
|||||||
#### **--ip**=*IP address*
|
#### **--ip**=*IP address*
|
||||||
|
|
||||||
Assign a static ip address to the pod. This option can be specified several times when play kube creates more than one pod.
|
Assign a static ip address to the pod. This option can be specified several times when play kube creates more than one pod.
|
||||||
|
Note: When joining multiple networks you should use the **--network name:ip=\<ip\>** syntax.
|
||||||
|
|
||||||
#### **--log-driver**=driver
|
#### **--log-driver**=driver
|
||||||
|
|
||||||
@ -167,15 +168,24 @@ This option is currently supported only by the **journald** log driver.
|
|||||||
#### **--mac-address**=*MAC address*
|
#### **--mac-address**=*MAC address*
|
||||||
|
|
||||||
Assign a static mac address to the pod. This option can be specified several times when play kube creates more than one pod.
|
Assign a static mac address to the pod. This option can be specified several times when play kube creates more than one pod.
|
||||||
|
Note: When joining multiple networks you should use the **--network name:mac=\<mac\>** syntax.
|
||||||
|
|
||||||
#### **--network**=*mode*, **--net**
|
#### **--network**=*mode*, **--net**
|
||||||
|
|
||||||
Change the network mode of the pod. The host and bridge network mode should be configured in the yaml file.
|
Change the network mode of the pod. The host network mode should be configured in the YAML file.
|
||||||
Valid _mode_ values are:
|
Valid _mode_ values are:
|
||||||
|
|
||||||
|
- **bridge[:OPTIONS,...]**: Create a network stack on the default bridge. This is the default for rootfull containers. It is possible to specify these additional options:
|
||||||
|
- **alias=name**: Add network-scoped alias for the container.
|
||||||
|
- **ip=IPv4**: Specify a static ipv4 address for this container.
|
||||||
|
- **ip=IPv6**: Specify a static ipv6 address for this container.
|
||||||
|
- **mac=MAC**: Specify a static mac address address for this container.
|
||||||
|
- **interface_name**: Specify a name for the created network interface inside the container.
|
||||||
|
|
||||||
|
For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.
|
||||||
|
- \<network name or ID\>[:OPTIONS,...]: Connect to a user-defined network; this is the network name or ID from a network created by **[podman network create](podman-network-create.1.md)**. Using the network name implies the bridge network mode. It is possible to specify the same options described under the bridge mode above. You can use the **--network** option multiple times to specify additional networks.
|
||||||
- **none**: Create a network namespace for the container but do not configure network interfaces for it, thus the container has no network connectivity.
|
- **none**: Create a network namespace for the container but do not configure network interfaces for it, thus the container has no network connectivity.
|
||||||
- **container:**_id_: Reuse another container's network stack.
|
- **container:**_id_: Reuse another container's network stack.
|
||||||
- **network**: Connect to a user-defined network, multiple networks should be comma-separated.
|
|
||||||
- **ns:**_path_: Path to a network namespace to join.
|
- **ns:**_path_: Path to a network namespace to join.
|
||||||
- **private**: Create a new namespace for the container. This will use the **bridge** mode for rootfull containers and **slirp4netns** for rootless ones.
|
- **private**: Create a new namespace for the container. This will use the **bridge** mode for rootfull containers and **slirp4netns** for rootless ones.
|
||||||
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
|
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
|
||||||
@ -253,9 +263,9 @@ $ podman play kube demo.yml --configmap configmap-foo.yml --configmap configmap-
|
|||||||
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
```
|
```
|
||||||
|
|
||||||
CNI network(s) can be specified as comma-separated list using ``--network``
|
Create a pod connected to two networks (called net1 and net2) with a static ip
|
||||||
```
|
```
|
||||||
$ podman play kube demo.yml --network cni1,cni2
|
$ podman play kube demo.yml --network net1:ip=10.89.1.5 --network net2:ip=10.89.10.10
|
||||||
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
52182811df2b1e73f36476003a66ec872101ea59034ac0d4d3a7b40903b955a6
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
|
|||||||
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
|
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
|
||||||
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
|
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
|
||||||
query := struct {
|
query := struct {
|
||||||
Network string `schema:"network"`
|
Network []string `schema:"network"`
|
||||||
TLSVerify bool `schema:"tlsVerify"`
|
TLSVerify bool `schema:"tlsVerify"`
|
||||||
LogDriver string `schema:"logDriver"`
|
LogDriver string `schema:"logDriver"`
|
||||||
LogOptions []string `schema:"logOptions"`
|
LogOptions []string `schema:"logOptions"`
|
||||||
@ -103,7 +103,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
|
|||||||
Authfile: authfile,
|
Authfile: authfile,
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
Network: query.Network,
|
Networks: query.Network,
|
||||||
NoHosts: query.NoHosts,
|
NoHosts: query.NoHosts,
|
||||||
Quiet: true,
|
Quiet: true,
|
||||||
LogDriver: query.LogDriver,
|
LogDriver: query.LogDriver,
|
||||||
|
@ -18,8 +18,10 @@ func (s *APIServer) registerPlayHandlers(r *mux.Router) error {
|
|||||||
// parameters:
|
// parameters:
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: network
|
// name: network
|
||||||
|
// type: array
|
||||||
|
// description: USe the network mode or specify an array of networks.
|
||||||
|
// items:
|
||||||
// type: string
|
// type: string
|
||||||
// description: Connect the pod to this network.
|
|
||||||
// - in: query
|
// - in: query
|
||||||
// name: tlsVerify
|
// name: tlsVerify
|
||||||
// type: boolean
|
// type: boolean
|
||||||
|
@ -15,8 +15,8 @@ type KubeOptions struct {
|
|||||||
Username *string
|
Username *string
|
||||||
// Password for authenticating against the registry.
|
// Password for authenticating against the registry.
|
||||||
Password *string
|
Password *string
|
||||||
// Network - name of the CNI network to connect to.
|
// Network - name of the networks to connect to.
|
||||||
Network *string
|
Network *[]string
|
||||||
// NoHosts - do not generate /etc/hosts file in pod's containers
|
// NoHosts - do not generate /etc/hosts file in pod's containers
|
||||||
NoHosts *bool
|
NoHosts *bool
|
||||||
// Quiet - suppress output when pulling images.
|
// Quiet - suppress output when pulling images.
|
||||||
|
@ -79,15 +79,15 @@ func (o *KubeOptions) GetPassword() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithNetwork set field Network to given value
|
// WithNetwork set field Network to given value
|
||||||
func (o *KubeOptions) WithNetwork(value string) *KubeOptions {
|
func (o *KubeOptions) WithNetwork(value []string) *KubeOptions {
|
||||||
o.Network = &value
|
o.Network = &value
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNetwork returns value of field Network
|
// GetNetwork returns value of field Network
|
||||||
func (o *KubeOptions) GetNetwork() string {
|
func (o *KubeOptions) GetNetwork() []string {
|
||||||
if o.Network == nil {
|
if o.Network == nil {
|
||||||
var z string
|
var z []string
|
||||||
return z
|
return z
|
||||||
}
|
}
|
||||||
return *o.Network
|
return *o.Network
|
||||||
|
@ -26,8 +26,8 @@ type PlayKubeOptions struct {
|
|||||||
Username string
|
Username string
|
||||||
// Password for authenticating against the registry.
|
// Password for authenticating against the registry.
|
||||||
Password string
|
Password string
|
||||||
// Network - name of the CNI network to connect to.
|
// Networks - name of the network to connect to.
|
||||||
Network string
|
Networks []string
|
||||||
// Quiet - suppress output when pulling images.
|
// Quiet - suppress output when pulling images.
|
||||||
Quiet bool
|
Quiet bool
|
||||||
// SignaturePolicy - path to a signature-policy file.
|
// SignaturePolicy - path to a signature-policy file.
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/containers/image/v5/types"
|
"github.com/containers/image/v5/types"
|
||||||
"github.com/containers/podman/v3/libpod"
|
"github.com/containers/podman/v3/libpod"
|
||||||
"github.com/containers/podman/v3/libpod/define"
|
"github.com/containers/podman/v3/libpod/define"
|
||||||
|
nettypes "github.com/containers/podman/v3/libpod/network/types"
|
||||||
"github.com/containers/podman/v3/pkg/autoupdate"
|
"github.com/containers/podman/v3/pkg/autoupdate"
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
"github.com/containers/podman/v3/pkg/specgen"
|
"github.com/containers/podman/v3/pkg/specgen"
|
||||||
@ -195,8 +196,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Network != "" {
|
ns, networks, netOpts, err := specgen.ParseNetworkFlag(options.Networks)
|
||||||
ns, networks, netOpts, err := specgen.ParseNetworkFlag([]string{options.Network})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -206,28 +206,41 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
}
|
}
|
||||||
|
|
||||||
podOpt.Net.Network = ns
|
podOpt.Net.Network = ns
|
||||||
if len(networks) > 0 {
|
|
||||||
podOpt.Net.Networks = networks
|
podOpt.Net.Networks = networks
|
||||||
}
|
|
||||||
if len(netOpts) > 0 {
|
|
||||||
podOpt.Net.NetworkOptions = netOpts
|
podOpt.Net.NetworkOptions = netOpts
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME This is very hard to support properly
|
// FIXME This is very hard to support properly with a good ux
|
||||||
// if len(options.StaticIPs) > *ipIndex {
|
if len(options.StaticIPs) > *ipIndex {
|
||||||
// podOpt.Net.StaticIP = &options.StaticIPs[*ipIndex]
|
if !podOpt.Net.Network.IsBridge() {
|
||||||
// } else if len(options.StaticIPs) > 0 {
|
errors.Wrap(define.ErrInvalidArg, "static ip addresses can only be set when the network mode is bridge")
|
||||||
// // only warn if the user has set at least one ip
|
}
|
||||||
// logrus.Warn("No more static ips left using a random one")
|
if len(podOpt.Net.Networks) != 1 {
|
||||||
// }
|
return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static ip addresses for more than network, use netname:ip=<ip> syntax to specify ips for more than network")
|
||||||
// if len(options.StaticMACs) > *ipIndex {
|
}
|
||||||
// podOpt.Net.StaticMAC = &options.StaticMACs[*ipIndex]
|
for name, netOpts := range podOpt.Net.Networks {
|
||||||
// } else if len(options.StaticIPs) > 0 {
|
netOpts.StaticIPs = append(netOpts.StaticIPs, options.StaticIPs[*ipIndex])
|
||||||
// // only warn if the user has set at least one mac
|
podOpt.Net.Networks[name] = netOpts
|
||||||
// logrus.Warn("No more static macs left using a random one")
|
}
|
||||||
// }
|
} else if len(options.StaticIPs) > 0 {
|
||||||
// *ipIndex++
|
// only warn if the user has set at least one ip
|
||||||
|
logrus.Warn("No more static ips left using a random one")
|
||||||
|
}
|
||||||
|
if len(options.StaticMACs) > *ipIndex {
|
||||||
|
if !podOpt.Net.Network.IsBridge() {
|
||||||
|
errors.Wrap(define.ErrInvalidArg, "static mac address can only be set when the network mode is bridge")
|
||||||
|
}
|
||||||
|
if len(podOpt.Net.Networks) != 1 {
|
||||||
|
return nil, errors.Wrap(define.ErrInvalidArg, "cannot set static mac address for more than network, use netname:mac=<mac> syntax to specify mac for more than network")
|
||||||
|
}
|
||||||
|
for name, netOpts := range podOpt.Net.Networks {
|
||||||
|
netOpts.StaticMAC = nettypes.HardwareAddr(options.StaticMACs[*ipIndex])
|
||||||
|
podOpt.Net.Networks[name] = netOpts
|
||||||
|
}
|
||||||
|
} else if len(options.StaticIPs) > 0 {
|
||||||
|
// only warn if the user has set at least one mac
|
||||||
|
logrus.Warn("No more static macs left using a random one")
|
||||||
|
}
|
||||||
|
*ipIndex++
|
||||||
|
|
||||||
p := specgen.NewPodSpecGenerator()
|
p := specgen.NewPodSpecGenerator()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
|
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, opts entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
|
||||||
options := new(play.KubeOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password)
|
options := new(play.KubeOptions).WithAuthfile(opts.Authfile).WithUsername(opts.Username).WithPassword(opts.Password)
|
||||||
options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps)
|
options.WithCertDir(opts.CertDir).WithQuiet(opts.Quiet).WithSignaturePolicy(opts.SignaturePolicy).WithConfigMaps(opts.ConfigMaps)
|
||||||
options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Network).WithSeccompProfileRoot(opts.SeccompProfileRoot)
|
options.WithLogDriver(opts.LogDriver).WithNetwork(opts.Networks).WithSeccompProfileRoot(opts.SeccompProfileRoot)
|
||||||
options.WithStaticIPs(opts.StaticIPs).WithStaticMACs(opts.StaticMACs)
|
options.WithStaticIPs(opts.StaticIPs).WithStaticMACs(opts.StaticMACs)
|
||||||
if len(opts.LogOptions) > 0 {
|
if len(opts.LogOptions) > 0 {
|
||||||
options.WithLogOptions(opts.LogOptions)
|
options.WithLogOptions(opts.LogOptions)
|
||||||
|
@ -2136,6 +2136,41 @@ spec:
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman play kube with multiple networks", func() {
|
||||||
|
ctr := getCtr(withImage(ALPINE))
|
||||||
|
pod := getPod(withCtr(ctr))
|
||||||
|
err := generateKubeYaml("pod", pod, kubeYaml)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
net1 := "net1" + stringid.GenerateNonCryptoID()
|
||||||
|
net2 := "net2" + stringid.GenerateNonCryptoID()
|
||||||
|
|
||||||
|
net := podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.11.0/24", net1})
|
||||||
|
net.WaitWithDefaultTimeout()
|
||||||
|
defer podmanTest.removeCNINetwork(net1)
|
||||||
|
Expect(net).Should(Exit(0))
|
||||||
|
|
||||||
|
net = podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.12.0/24", net2})
|
||||||
|
net.WaitWithDefaultTimeout()
|
||||||
|
defer podmanTest.removeCNINetwork(net2)
|
||||||
|
Expect(net).Should(Exit(0))
|
||||||
|
|
||||||
|
ip1 := "10.0.11.5"
|
||||||
|
ip2 := "10.0.12.10"
|
||||||
|
|
||||||
|
kube := podmanTest.Podman([]string{"play", "kube", "--network", net1 + ":ip=" + ip1, "--network", net2 + ":ip=" + ip2, kubeYaml})
|
||||||
|
kube.WaitWithDefaultTimeout()
|
||||||
|
Expect(kube).Should(Exit(0))
|
||||||
|
|
||||||
|
inspect := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "ip", "addr"})
|
||||||
|
inspect.WaitWithDefaultTimeout()
|
||||||
|
Expect(inspect).Should(Exit(0))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring(ip1))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring(ip2))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("eth0"))
|
||||||
|
Expect(inspect.OutputToString()).To(ContainSubstring("eth1"))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman play kube test with network portbindings", func() {
|
It("podman play kube test with network portbindings", func() {
|
||||||
ip := "127.0.0.100"
|
ip := "127.0.0.100"
|
||||||
port := "5000"
|
port := "5000"
|
||||||
|
@ -104,8 +104,6 @@ RELABEL="system_u:object_r:container_file_t:s0"
|
|||||||
TESTDIR=$PODMAN_TMPDIR/testdir
|
TESTDIR=$PODMAN_TMPDIR/testdir
|
||||||
mkdir -p $TESTDIR
|
mkdir -p $TESTDIR
|
||||||
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
|
||||||
run_podman 125 play kube --network bridge $PODMAN_TMPDIR/test.yaml
|
|
||||||
is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail with --network host"
|
|
||||||
run_podman 125 play kube --network host $PODMAN_TMPDIR/test.yaml
|
run_podman 125 play kube --network host $PODMAN_TMPDIR/test.yaml
|
||||||
is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail with --network host"
|
is "$output" ".*invalid value passed to --network: bridge or host networking must be configured in YAML" "podman plan-network should fail with --network host"
|
||||||
run_podman play kube --network slirp4netns:port_handler=slirp4netns $PODMAN_TMPDIR/test.yaml
|
run_podman play kube --network slirp4netns:port_handler=slirp4netns $PODMAN_TMPDIR/test.yaml
|
||||||
|
Reference in New Issue
Block a user