mirror of
https://github.com/lingble/talos.git
synced 2025-12-03 22:33:50 +00:00
feat: add CNI, and pod and service CIDR to configurator
This adds more methods to the Cluster interface that allows for more granular control of the cluster network settings. Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/goroutine"
|
"github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/goroutine"
|
||||||
"github.com/talos-systems/talos/pkg/config"
|
"github.com/talos-systems/talos/pkg/config"
|
||||||
"github.com/talos-systems/talos/pkg/constants"
|
"github.com/talos-systems/talos/pkg/constants"
|
||||||
|
tnet "github.com/talos-systems/talos/pkg/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bootkube implements the Service interface. It serves as the concrete type with
|
// Bootkube implements the Service interface. It serves as the concrete type with
|
||||||
@@ -125,11 +126,11 @@ func generateAssets(config config.Configurator) (err error) {
|
|||||||
}
|
}
|
||||||
apiServers = append(apiServers, u)
|
apiServers = append(apiServers, u)
|
||||||
|
|
||||||
_, podCIDR, err := net.ParseCIDR("10.2.0.0/16")
|
_, podCIDR, err := net.ParseCIDR(config.Cluster().Network().PodCIDR())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, serviceCIDR, err := net.ParseCIDR("10.3.0.0/24")
|
_, serviceCIDR, err := net.ParseCIDR(config.Cluster().Network().ServiceCIDR())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -154,6 +155,16 @@ func generateAssets(config config.Configurator) (err error) {
|
|||||||
return errors.Wrap(err, "failed to parse Kubernetes key")
|
return errors.Wrap(err, "failed to parse Kubernetes key")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apiServiceIP, err := tnet.NthIPInNetwork(serviceCIDR, 1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsServiceIP, err := tnet.NthIPInNetwork(serviceCIDR, 10)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
conf := asset.Config{
|
conf := asset.Config{
|
||||||
CACert: k8sCA,
|
CACert: k8sCA,
|
||||||
CAPrivKey: k8sKey,
|
CAPrivKey: k8sKey,
|
||||||
@@ -163,11 +174,11 @@ func generateAssets(config config.Configurator) (err error) {
|
|||||||
EtcdServers: []*url.URL{etcdServer},
|
EtcdServers: []*url.URL{etcdServer},
|
||||||
EtcdUseTLS: true,
|
EtcdUseTLS: true,
|
||||||
APIServers: apiServers,
|
APIServers: apiServers,
|
||||||
APIServiceIP: net.ParseIP("10.3.0.1"),
|
APIServiceIP: apiServiceIP,
|
||||||
DNSServiceIP: net.ParseIP("10.3.0.10"),
|
DNSServiceIP: dnsServiceIP,
|
||||||
PodCIDR: podCIDR,
|
PodCIDR: podCIDR,
|
||||||
ServiceCIDR: serviceCIDR,
|
ServiceCIDR: serviceCIDR,
|
||||||
NetworkProvider: "flannel",
|
NetworkProvider: config.Cluster().Network().CNI(),
|
||||||
AltNames: altNames,
|
AltNames: altNames,
|
||||||
Images: asset.DefaultImages,
|
Images: asset.DefaultImages,
|
||||||
BootstrapSecretsSubdir: "/assets/tls",
|
BootstrapSecretsSubdir: "/assets/tls",
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ type Cluster interface {
|
|||||||
AESCBCEncryptionSecret() string
|
AESCBCEncryptionSecret() string
|
||||||
Config(machine.Type) (string, error)
|
Config(machine.Type) (string, error)
|
||||||
Etcd() Etcd
|
Etcd() Etcd
|
||||||
|
Network() Network
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network defines the requirements for a config that pertains to cluster
|
||||||
|
// network options.
|
||||||
|
type Network interface {
|
||||||
|
CNI() string
|
||||||
|
PodCIDR() string
|
||||||
|
ServiceCIDR() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Etcd defines the requirements for a config that pertains to etcd related
|
// Etcd defines the requirements for a config that pertains to etcd related
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/talos-systems/talos/pkg/config/cluster"
|
"github.com/talos-systems/talos/pkg/config/cluster"
|
||||||
"github.com/talos-systems/talos/pkg/config/machine"
|
"github.com/talos-systems/talos/pkg/config/machine"
|
||||||
|
"github.com/talos-systems/talos/pkg/constants"
|
||||||
"github.com/talos-systems/talos/pkg/crypto/x509"
|
"github.com/talos-systems/talos/pkg/crypto/x509"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ import (
|
|||||||
type ClusterConfig struct {
|
type ClusterConfig struct {
|
||||||
ControlPlane *ControlPlaneConfig `yaml:"controlPlane"`
|
ControlPlane *ControlPlaneConfig `yaml:"controlPlane"`
|
||||||
ClusterName string `yaml:"clusterName,omitempty"`
|
ClusterName string `yaml:"clusterName,omitempty"`
|
||||||
Network *ClusterNetworkConfig `yaml:"network,omitempty"`
|
ClusterNetwork *ClusterNetworkConfig `yaml:"network,omitempty"`
|
||||||
BootstrapToken string `yaml:"token,omitempty"`
|
BootstrapToken string `yaml:"token,omitempty"`
|
||||||
CertificateKey string `yaml:"certificateKey"`
|
CertificateKey string `yaml:"certificateKey"`
|
||||||
ClusterAESCBCEncryptionSecret string `yaml:"aescbcEncryptionSecret"`
|
ClusterAESCBCEncryptionSecret string `yaml:"aescbcEncryptionSecret"`
|
||||||
@@ -67,6 +68,7 @@ type EtcdConfig struct {
|
|||||||
|
|
||||||
// ClusterNetworkConfig represents kube networking config vals
|
// ClusterNetworkConfig represents kube networking config vals
|
||||||
type ClusterNetworkConfig struct {
|
type ClusterNetworkConfig struct {
|
||||||
|
CNI string `yaml:"cni"`
|
||||||
DNSDomain string `yaml:"dnsDomain"`
|
DNSDomain string `yaml:"dnsDomain"`
|
||||||
PodSubnet []string `yaml:"podSubnets"`
|
PodSubnet []string `yaml:"podSubnets"`
|
||||||
ServiceSubnet []string `yaml:"serviceSubnets"`
|
ServiceSubnet []string `yaml:"serviceSubnets"`
|
||||||
@@ -139,3 +141,35 @@ func (c *ClusterConfig) Secret() string {
|
|||||||
}
|
}
|
||||||
return parts[1]
|
return parts[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Network implements the Configurator interface.
|
||||||
|
func (c *ClusterConfig) Network() cluster.Network {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// CNI implements the Configurator interface.
|
||||||
|
func (c *ClusterConfig) CNI() string {
|
||||||
|
if c.ClusterNetwork.CNI == "" {
|
||||||
|
return constants.DefaultCNI
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ClusterNetwork.CNI
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodCIDR implements the Configurator interface.
|
||||||
|
func (c *ClusterConfig) PodCIDR() string {
|
||||||
|
if len(c.ClusterNetwork.PodSubnet) == 0 {
|
||||||
|
return constants.DefaultPodCIDR
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ClusterNetwork.PodSubnet[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceCIDR implements the Configurator interface.
|
||||||
|
func (c *ClusterConfig) ServiceCIDR() string {
|
||||||
|
if len(c.ClusterNetwork.ServiceSubnet) == 0 {
|
||||||
|
return constants.DefaultServiceCIDR
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ClusterNetwork.ServiceSubnet[0]
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func initUd(in *Input) (string, error) {
|
|||||||
EtcdConfig: &v1alpha1.EtcdConfig{
|
EtcdConfig: &v1alpha1.EtcdConfig{
|
||||||
RootCA: in.Certs.Etcd,
|
RootCA: in.Certs.Etcd,
|
||||||
},
|
},
|
||||||
Network: &v1alpha1.ClusterNetworkConfig{
|
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||||
DNSDomain: in.ServiceDomain,
|
DNSDomain: in.ServiceDomain,
|
||||||
PodSubnet: in.PodNet,
|
PodSubnet: in.PodNet,
|
||||||
ServiceSubnet: in.ServiceNet,
|
ServiceSubnet: in.ServiceNet,
|
||||||
|
|||||||
@@ -233,6 +233,15 @@ const (
|
|||||||
|
|
||||||
// DefaultLogPath is the default path to the log storage directory.
|
// DefaultLogPath is the default path to the log storage directory.
|
||||||
DefaultLogPath = SystemRunPath + "/log"
|
DefaultLogPath = SystemRunPath + "/log"
|
||||||
|
|
||||||
|
// DefaultCNI is the default CNI.
|
||||||
|
DefaultCNI = "flannel"
|
||||||
|
|
||||||
|
// DefaultPodCIDR is the default pod CIDR block.
|
||||||
|
DefaultPodCIDR = "10.244.0.0/16"
|
||||||
|
|
||||||
|
// DefaultServiceCIDR is the default service CIDR block.
|
||||||
|
DefaultServiceCIDR = "10.96.0.0/12"
|
||||||
)
|
)
|
||||||
|
|
||||||
// See https://linux.die.net/man/3/klogctl
|
// See https://linux.die.net/man/3/klogctl
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ package net
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPAddrs finds and returns a list of non-loopback IPv4 addresses of the
|
// IPAddrs finds and returns a list of non-loopback IPv4 addresses of the
|
||||||
@@ -40,3 +42,24 @@ func FormatAddress(addr string) string {
|
|||||||
}
|
}
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NthIPInNetwork takes an IPNet and returns the nth IP in it.
|
||||||
|
func NthIPInNetwork(network *net.IPNet, n int) (net.IP, error) {
|
||||||
|
ip := network.IP
|
||||||
|
dst := make([]byte, len(ip))
|
||||||
|
copy(dst, ip)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
for j := len(dst) - 1; j >= 0; j-- {
|
||||||
|
dst[j]++
|
||||||
|
if dst[j] > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.Contains(dst) {
|
||||||
|
return dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errors.New("network does not contain enough IPs")
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
@@ -23,3 +25,73 @@ func TestFormatAddress(t *testing.T) {
|
|||||||
assert.Equal(t, FormatAddress("192.168.1.1"), "192.168.1.1")
|
assert.Equal(t, FormatAddress("192.168.1.1"), "192.168.1.1")
|
||||||
assert.Equal(t, FormatAddress("alpha.beta.gamma.com"), "alpha.beta.gamma.com")
|
assert.Equal(t, FormatAddress("alpha.beta.gamma.com"), "alpha.beta.gamma.com")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint: scopelint
|
||||||
|
func TestNthIPInNetwork(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
network *net.IPNet
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want net.IP
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "increment IPv4 by 1",
|
||||||
|
args: args{
|
||||||
|
network: &net.IPNet{
|
||||||
|
IP: net.IP{10, 96, 0, 0},
|
||||||
|
Mask: net.IPMask{255, 255, 255, 0},
|
||||||
|
},
|
||||||
|
n: 1,
|
||||||
|
},
|
||||||
|
want: net.IP{10, 96, 0, 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "increment IPv4 by 10",
|
||||||
|
args: args{
|
||||||
|
network: &net.IPNet{
|
||||||
|
IP: net.IP{10, 96, 0, 0},
|
||||||
|
Mask: net.IPMask{255, 255, 255, 0},
|
||||||
|
},
|
||||||
|
n: 10,
|
||||||
|
},
|
||||||
|
want: net.IP{10, 96, 0, 10},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "increment IPv6 by 1",
|
||||||
|
args: args{
|
||||||
|
network: &net.IPNet{
|
||||||
|
IP: net.ParseIP("2001:db8:a0b:12f0::1"),
|
||||||
|
Mask: net.IPMask{255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
},
|
||||||
|
n: 1,
|
||||||
|
},
|
||||||
|
want: net.ParseIP("2001:db8:a0b:12f0::2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "increment IPv6 by 10",
|
||||||
|
args: args{
|
||||||
|
network: &net.IPNet{
|
||||||
|
IP: net.ParseIP("2001:db8:a0b:12f0::1"),
|
||||||
|
Mask: net.IPMask{255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
},
|
||||||
|
n: 10,
|
||||||
|
},
|
||||||
|
want: net.ParseIP("2001:db8:a0b:12f0::b"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := NthIPInNetwork(tt.args.network, tt.args.n)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("NthFromIP() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user