start coupling network to clusters

pull/227/head
iwilltry42 5 years ago
parent 1ca9193776
commit 5851da3ef3
  1. 25
      cmd/create/createCluster.go
  2. 22
      pkg/cluster/cluster.go
  3. 9
      pkg/runtimes/containerd/network.go
  4. 22
      pkg/runtimes/docker/network.go
  5. 3
      pkg/runtimes/runtime.go
  6. 18
      pkg/types/types.go

@ -55,12 +55,14 @@ func NewCmdCreateCluster() *cobra.Command {
cmd.Flags().StringArrayP("api-port", "a", []string{"6443"}, "Specify the Kubernetes API server port (Format: `--api-port [HOST:]HOSTPORT[@NODEFILTER]`") // TODO: how to handle this for multi-master setups?
cmd.Flags().IntP("masters", "m", 1, "Specify how many masters you want to create")
cmd.Flags().IntP("workers", "w", 0, "Specify how many workers you want to create")
cmd.Flags().String("config", "", "Specify a cluster configuration file") // TODO: to implement
// cmd.Flags().String("config", "", "Specify a cluster configuration file") // TODO: to implement
cmd.Flags().String("image", k3d.DefaultK3sImageRepo, "Specify k3s image that you want to use for the nodes") // TODO: get image version
cmd.Flags().String("network", "", "Join an existing network")
cmd.Flags().String("secret", "", "Specify a cluster secret. By default, we generate one.")
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `--volume [SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`")
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)")
cmd.Flags().Bool("no-lb", false, "Disable automatic deployment of a load balancer in Multi-Master setups")
cmd.Flags().String("lb-port", "0.0.0.0:6443", "Specify port to be exposed by the master load balancer (Format: `[HOST:]HOSTPORT)")
// add subcommands
@ -172,6 +174,18 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime,
exposeAPIToFiltersMap[exposeAPI] = filters
}
// --no-lb
noLB, err := cmd.Flags().GetBool("no-lb")
if err != nil {
log.Fatalln(err)
}
// --lb-port
lbPort, err := cmd.Flags().GetString("lb-port")
if err != nil {
log.Fatalln(err)
}
// --volume
volumeFlags, err := cmd.Flags().GetStringArray("volume")
if err != nil {
@ -303,5 +317,14 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string) (runtimes.Runtime,
}
}
// TODO: create load balancer and other util containers // TODO: for now, this will only work with the docker provider (?) -> can replace dynamic docker lookup with static traefik config (?)
if masterCount > 1 && !noLB { // TODO: add traefik to the same network and add traefik labels to the master node containers
log.Debugln("Creating LB in front of master nodes")
cluster.MasterLoadBalancer = &k3d.ClusterLoadbalancer{
Image: k3d.DefaultLBImage,
ExposedPort: lbPort,
}
}
return runtime, cluster
}

@ -45,12 +45,19 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
}
// create cluster network or use an existing one
networkID, err := runtime.CreateNetworkIfNotPresent(cluster.Network)
networkID, networkExists, err := runtime.CreateNetworkIfNotPresent(cluster.Network)
if err != nil {
log.Errorln("Failed to create cluster network")
return err
}
cluster.Network = networkID
extraLabels := map[string]string{
"k3d.cluster.network": networkID,
"k3d.cluster.network.external": "false",
}
if networkExists {
extraLabels["k3d.cluster.network.external"] = "true" // if the network wasn't created, we say that it's managed externally (important for cluster deletion)
}
/*
* Cluster Secret
@ -77,6 +84,11 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
node.Labels["k3d.cluster"] = cluster.Name
node.Env = append(node.Env, fmt.Sprintf("K3S_CLUSTER_SECRET=%s", cluster.Secret))
// append extra labels
for k, v := range extraLabels {
node.Labels[k] = v
}
// node role specific settings
suffix := 0
if node.Role == k3d.MasterRole {
@ -121,7 +133,13 @@ func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
}
}
// TODO: remove network
if network, ok := cluster.Nodes[0].Labels["k3d.cluster.network"]; ok {
if cluster.Nodes[0].Labels["k3d.cluster.network.external"] == "false" {
if err := runtime.DeleteNetwork(network); err != nil {
log.Warningf("Failed to delete cluster network '%s': Try to delete it manually", network)
}
}
}
if failed > 0 {
return fmt.Errorf("Failed to delete %d nodes: Try to delete them manually", failed)

@ -22,6 +22,11 @@ THE SOFTWARE.
package containerd
// CreateNetworkIfNotPresent creates a new docker network
func (d Containerd) CreateNetworkIfNotPresent(name string) (string, error) {
return "", nil
func (d Containerd) CreateNetworkIfNotPresent(name string) (string, bool, error) {
return "", false, nil
}
// DeleteNetwork deletes a network
func DeleteNetwork(name string) error {
return nil
}

@ -23,6 +23,7 @@ package docker
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
@ -32,18 +33,20 @@ import (
)
// CreateNetworkIfNotPresent creates a new docker network
func (d Docker) CreateNetworkIfNotPresent(name string) (string, error) {
// @return: network name, exists, error
func (d Docker) CreateNetworkIfNotPresent(name string) (string, bool, error) {
// (0) create new docker client
ctx := context.Background()
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Errorln("Failed to create docker client")
return "", err
return "", false, err
}
// (1) configure list filters
args := GetDefaultObjectLabelsFilter(name)
args := GetDefaultObjectLabelsFilter("")
args.Del("label", fmt.Sprintf("k3d.cluster=%s", "")) // We don't filter for cluster name here
args.Add("name", name)
// (2) get filtered list of networks
@ -52,7 +55,7 @@ func (d Docker) CreateNetworkIfNotPresent(name string) (string, error) {
})
if err != nil {
log.Errorln("Failed to list docker networks")
return "", err
return "", false, err
}
// (2.1) If possible, return an existing network
@ -62,7 +65,7 @@ func (d Docker) CreateNetworkIfNotPresent(name string) (string, error) {
if len(networkList) > 0 {
log.Infof("Network with name '%s' already exists with ID '%s'", name, networkList[0].ID)
return networkList[0].ID, nil
return networkList[0].ID, true, nil
}
// (3) Create a new network
@ -71,9 +74,14 @@ func (d Docker) CreateNetworkIfNotPresent(name string) (string, error) {
})
if err != nil {
log.Errorln("Failed to create network")
return "", err
return "", false, err
}
log.Infof("Created network '%s'", name)
return network.ID, nil
return network.ID, false, nil
}
// DeleteNetwork deletes a network
func DeleteNetwork(name string) error {
return nil
}

@ -41,8 +41,9 @@ type Runtime interface {
CreateNode(*k3d.Node) error
DeleteNode(*k3d.Node) error
GetNodesByLabel(map[string]string) ([]*k3d.Node, error)
CreateNetworkIfNotPresent(name string) (string, error)
CreateNetworkIfNotPresent(name string) (string, bool, error) // @return NETWORK_NAME, EXISTS, ERROR
GetKubeconfig(*k3d.Node) (io.ReadCloser, error)
DeleteNetwork(name string) error
// StartContainer() error
// ExecContainer() error
// StopContainer() error

@ -35,6 +35,9 @@ const DefaultClusterNameMaxLength = 32
// DefaultK3sImageRepo specifies the default image repository for the used k3s image
const DefaultK3sImageRepo = "docker.io/rancher/k3s"
// DefaultLBImage defines the default cluster load balancer image
const DefaultLBImage = "docker.io/library/traefik:v2.0"
// DefaultObjectNamePrefix defines the name prefix for every object created by k3d
const DefaultObjectNamePrefix = "k3d"
@ -71,10 +74,11 @@ var DefaultNodeEnv = []string{
// Cluster describes a k3d cluster
type Cluster struct {
Name string `yaml:"name" json:"name,omitempty"`
Network string `yaml:"network" json:"network,omitempty"`
Secret string `yaml:"cluster_secret" json:"clusterSecret,omitempty"`
Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"`
Name string `yaml:"name" json:"name,omitempty"`
Network string `yaml:"network" json:"network,omitempty"`
Secret string `yaml:"cluster_secret" json:"clusterSecret,omitempty"`
Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"`
MasterLoadBalancer *ClusterLoadbalancer `yaml:"master_loadbalancer" json:"masterLoadBalancer,omitempty"`
}
// Node describes a k3d node
@ -113,3 +117,9 @@ type WorkerOpts struct{}
func GetDefaultObjectName(name string) string {
return fmt.Sprintf("%s-%s", DefaultObjectNamePrefix, name)
}
// ClusterLoadbalancer describes a loadbalancer deployed in front of a multi-master cluster
type ClusterLoadbalancer struct {
Image string
ExposedPort string `yaml:"exposed_port" json:"exposedPort,omitempty"`
}

Loading…
Cancel
Save