add some more portmapping work
This commit is contained in:
parent
2092ceaaa9
commit
8e29ad4f1a
@ -301,7 +301,7 @@ func NewCmdClusterCreate() *cobra.Command {
|
|||||||
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `[SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -v /my/path@agent[0,1] -v /tmp/test:/tmp/other@server[0]`")
|
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `[SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 -v /my/path@agent[0,1] -v /tmp/test:/tmp/other@server[0]`")
|
||||||
_ = ppViper.BindPFlag("cli.volumes", cmd.Flags().Lookup("volume"))
|
_ = ppViper.BindPFlag("cli.volumes", cmd.Flags().Lookup("volume"))
|
||||||
|
|
||||||
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d cluster create --agents 2 -p 8080:80@agent[0] -p 8081@agent[1]`")
|
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers (via the serverlb) to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d cluster create --agents 2 -p 8080:80@agent[0] -p 8081@agent[1]`")
|
||||||
_ = ppViper.BindPFlag("cli.ports", cmd.Flags().Lookup("port"))
|
_ = ppViper.BindPFlag("cli.ports", cmd.Flags().Lookup("port"))
|
||||||
|
|
||||||
cmd.Flags().StringArrayP("k3s-node-label", "", nil, "Add label to k3s node (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 --k3s-node-label \"my.label@agent[0,1]\" --k3s-node-label \"other.label=somevalue@server[0]\"`")
|
cmd.Flags().StringArrayP("k3s-node-label", "", nil, "Add label to k3s node (Format: `KEY[=VALUE][@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d cluster create --agents 2 --k3s-node-label \"my.label@agent[0,1]\" --k3s-node-label \"other.label=somevalue@server[0]\"`")
|
||||||
|
@ -386,19 +386,7 @@ func NodeCreate(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, c
|
|||||||
/* global node configuration (applies for any node role) */
|
/* global node configuration (applies for any node role) */
|
||||||
|
|
||||||
// ### Labels ###
|
// ### Labels ###
|
||||||
labels := make(map[string]string)
|
node.FillRuntimeLabels()
|
||||||
for k, v := range k3d.DefaultRuntimeLabels {
|
|
||||||
labels[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range k3d.DefaultRuntimeLabelsVar {
|
|
||||||
labels[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range node.RuntimeLabels {
|
|
||||||
labels[k] = v
|
|
||||||
}
|
|
||||||
node.RuntimeLabels = labels
|
|
||||||
// second most important: the node role label
|
|
||||||
node.RuntimeLabels[k3d.LabelRole] = string(node.Role)
|
|
||||||
|
|
||||||
for k, v := range node.K3sNodeLabels {
|
for k, v := range node.K3sNodeLabels {
|
||||||
node.Args = append(node.Args, "--node-label", fmt.Sprintf("%s=%s", k, v))
|
node.Args = append(node.Args, "--node-label", fmt.Sprintf("%s=%s", k, v))
|
||||||
|
94
pkg/types/loadbalancer.go
Normal file
94
pkg/types/loadbalancer.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2020-2021 The k3d Author(s)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package types
|
||||||
|
|
||||||
|
/* DESCRIPTION
|
||||||
|
* The Loadbalancer is a customized NGINX container running side-by-side with the cluster, NOT INSIDE IT.
|
||||||
|
* It is used to do plain proxying of tcp/udp ports to the k3d node containers.
|
||||||
|
* One advantage of this approach is, that we can add new ports while the cluster is still running by re-creating
|
||||||
|
* the loadbalancer and adding the new port config in the NGINX config. As the loadbalancer doesn't hold any state
|
||||||
|
* (apart from the config file), it can easily be re-created in just a few seconds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loadbalancer Definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
type Loadbalancer struct {
|
||||||
|
Node Node `mapstructure:",squash" yaml:",inline"` // the underlying node
|
||||||
|
Config LoadbalancerConfig `mapstructure:"config" yaml:"config"` // its configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLoadbalancer() *Loadbalancer {
|
||||||
|
return &Loadbalancer{
|
||||||
|
Node: Node{
|
||||||
|
Role: LoadBalancerRole,
|
||||||
|
Image: GetLoadbalancerImage(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loadbalancer Configuration
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* LoadbalancerConfig defines the coarse file structure to configure the k3d-proxy
|
||||||
|
* Example:
|
||||||
|
* ports:
|
||||||
|
* 1234.tcp:
|
||||||
|
* - k3d-k3s-default-server-0
|
||||||
|
* - k3d-k3s-default-server-1
|
||||||
|
* 4321.udp:
|
||||||
|
* - k3d-k3s-default-agent-0
|
||||||
|
* - k3d-k3s-default-agent-1
|
||||||
|
*/
|
||||||
|
type LoadbalancerConfig struct {
|
||||||
|
Ports map[string][]string `yaml:"ports"`
|
||||||
|
Settings LoadBalancerSettings `yaml:"settings"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoadBalancerSettings struct {
|
||||||
|
WorkerProcesses int `yaml:"workerProcesses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultLoadbalancerConfigPath = "/etc/confd/values.yaml"
|
||||||
|
DefaultLoadbalancerWorkerProcesses = 1024
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoadbalancerCreateOpts struct {
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// HasLoadBalancer returns true if cluster has a loadbalancer node
|
||||||
|
func (c *Cluster) HasLoadBalancer() bool {
|
||||||
|
for _, node := range c.Nodes {
|
||||||
|
if node.Role == LoadBalancerRole {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
39
pkg/types/node.go
Normal file
39
pkg/types/node.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2020-2021 The k3d Author(s)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package types
|
||||||
|
|
||||||
|
func (node *Node) FillRuntimeLabels() {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
for k, v := range DefaultRuntimeLabels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range DefaultRuntimeLabelsVar {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range node.RuntimeLabels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
node.RuntimeLabels = labels
|
||||||
|
// second most important: the node role label
|
||||||
|
node.RuntimeLabels[LabelRole] = string(node.Role)
|
||||||
|
|
||||||
|
}
|
@ -297,16 +297,6 @@ func (c *Cluster) AgentCountRunning() (int, int) {
|
|||||||
return agentCount, agentsRunning
|
return agentCount, agentsRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasLoadBalancer returns true if cluster has a loadbalancer node
|
|
||||||
func (c *Cluster) HasLoadBalancer() bool {
|
|
||||||
for _, node := range c.Nodes {
|
|
||||||
if node.Role == LoadBalancerRole {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeIP struct {
|
type NodeIP struct {
|
||||||
IP netaddr.IP
|
IP netaddr.IP
|
||||||
Static bool
|
Static bool
|
||||||
@ -413,35 +403,3 @@ type RegistryExternal struct {
|
|||||||
Host string `yaml:"host" json:"host"`
|
Host string `yaml:"host" json:"host"`
|
||||||
Port string `yaml:"port" json:"port"`
|
Port string `yaml:"port" json:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Loadbalancer
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* LoadbalancerConfig defines the coarse file structure to configure the k3d-proxy
|
|
||||||
* Example:
|
|
||||||
* ports:
|
|
||||||
* 1234.tcp:
|
|
||||||
* - k3d-k3s-default-server-0
|
|
||||||
* - k3d-k3s-default-server-1
|
|
||||||
* 4321.udp:
|
|
||||||
* - k3d-k3s-default-agent-0
|
|
||||||
* - k3d-k3s-default-agent-1
|
|
||||||
*/
|
|
||||||
type LoadbalancerConfig struct {
|
|
||||||
Ports map[string][]string `yaml:"ports"`
|
|
||||||
Settings LoadBalancerSettings `yaml:"settings"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoadBalancerSettings struct {
|
|
||||||
WorkerProcesses int `yaml:"workerProcesses"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
DefaultLoadbalancerConfigPath = "/etc/confd/values.yaml"
|
|
||||||
DefaultLoadbalancerWorkerProcesses = 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
type LoadbalancerCreateOpts struct {
|
|
||||||
Labels map[string]string
|
|
||||||
}
|
|
||||||
|
@ -31,15 +31,26 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type NodeFilterSuffix string
|
||||||
|
|
||||||
|
const (
|
||||||
|
NodeFilterSuffixNone NodeFilterSuffix = "none"
|
||||||
|
NodeFilterMapKeyAll = "all"
|
||||||
|
)
|
||||||
|
|
||||||
// Regexp pattern to match node filters
|
// Regexp pattern to match node filters
|
||||||
var filterRegexp = regexp.MustCompile(`^(?P<group>server|agent|loadbalancer|all)(?P<subsetSpec>\[(?P<subset>(?P<subsetList>(\d+,?)+)|(?P<subsetRange>\d*:\d*)|(?P<subsetWildcard>\*))\])?$`)
|
var NodeFilterRegexp = regexp.MustCompile(`^(?P<group>server|servers|agent|agents|loadbalancer|all)(?P<subsetSpec>:(?P<subset>(?P<subsetList>(\d+,?)+)|(?P<subsetRange>\d*-\d*)|(?P<subsetWildcard>\*)))?(?P<suffix>:[[:alpha:]]+)?$`)
|
||||||
|
|
||||||
// FilterNodes takes a string filter to return a filtered list of nodes
|
// FilterNodes takes a string filter to return a filtered list of nodes
|
||||||
func FilterNodes(nodes []*k3d.Node, filters []string) ([]*k3d.Node, error) {
|
func FilterNodes(nodes []*k3d.Node, filters []string) (map[string][]*k3d.Node, error) {
|
||||||
|
|
||||||
|
result := map[string][]*k3d.Node{
|
||||||
|
NodeFilterMapKeyAll: nodes,
|
||||||
|
}
|
||||||
|
|
||||||
if len(filters) == 0 || len(filters[0]) == 0 {
|
if len(filters) == 0 || len(filters[0]) == 0 {
|
||||||
log.Warnln("No node filter specified")
|
log.Warnln("No node filter specified")
|
||||||
return nodes, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// map roles to subsets
|
// map roles to subsets
|
||||||
@ -64,21 +75,21 @@ func FilterNodes(nodes []*k3d.Node, filters []string) ([]*k3d.Node, error) {
|
|||||||
for _, filter := range filters {
|
for _, filter := range filters {
|
||||||
|
|
||||||
// match regex with capturing groups
|
// match regex with capturing groups
|
||||||
match := filterRegexp.FindStringSubmatch(filter)
|
match := NodeFilterRegexp.FindStringSubmatch(filter)
|
||||||
|
|
||||||
if len(match) == 0 {
|
if len(match) == 0 {
|
||||||
return nil, fmt.Errorf("Failed to parse node filters: invalid format or empty subset in '%s'", filter)
|
return nil, fmt.Errorf("Failed to parse node filters: invalid format or empty subset in '%s'", filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// map capturing group names to submatches
|
// map capturing group names to submatches
|
||||||
submatches := MapSubexpNames(filterRegexp.SubexpNames(), match)
|
submatches := MapSubexpNames(NodeFilterRegexp.SubexpNames(), match)
|
||||||
|
|
||||||
// if one of the filters is 'all', we only return this and drop all others
|
// if one of the filters is 'all', we only return this and drop all others
|
||||||
if submatches["group"] == "all" {
|
if submatches["group"] == "all" {
|
||||||
if len(filters) > 1 {
|
if len(filters) > 1 {
|
||||||
log.Warnf("Node filter 'all' set, but more were specified in '%+v'", filters)
|
log.Warnf("Node filter 'all' set, but more were specified in '%+v'", filters)
|
||||||
}
|
}
|
||||||
return nodes, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose the group of nodes to operate on
|
// Choose the group of nodes to operate on
|
||||||
|
Loading…
Reference in New Issue
Block a user