Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate the Calico ipip mode in favor of bird #4676

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ k0s can also work with externally managed Etcd cluster. If this is configured, k

| Element | Description |
|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mode` | `vxlan` (default), `ipip` or `bird` |
| `mode` | Indicates the Calico backend to use. Either `bird` or `vxlan` (default). The deprecated legacy value `ipip` is also accepted. |
| `overlay` | Overlay mode: `Always` (default), `CrossSubnet` or `Never` (requires `mode=vxlan` to disable calico overlay-network). |
| `vxlanPort` | The UDP port for VXLAN (default: `4789`). |
| `vxlanVNI` | The virtual network ID for VXLAN (default: `4096`). |
Expand Down
18 changes: 7 additions & 11 deletions docs/internal/upgrading-calico.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,19 @@ That'll make it easier to spot any needed changes.

`static/manifests/calico/DaemonSet/calico-node.yaml`:

- variable-based support for both vxlan and ipip (search for `ipip` to find):
- variable-based support for both vxlan and bird (search for `.Mode` to find):

```yaml
{{- if eq .Mode "ipip" }}
# Enable IPIP
- name: CALICO_IPV4POOL_IPIP
value: {{ .Overlay }}
value: "{{ if eq .Mode "bird" }}{{ .Overlay }}{{ else }}Never{{ end }}"
# Enable or Disable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: "Never"
{{- else if eq .Mode "vxlan" }}
# Disable IPIP
- name: CALICO_IPV4POOL_IPIP
value: "Never"
# Enable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: {{ .Overlay }}
value: "{{ if eq .Mode "vxlan" }}{{ .Overlay }}{{ else }}Never{{ end }}"
# Enable or Disable VXLAN on the default IPv6 IP pool.
- name: CALICO_IPV6POOL_VXLAN
value: "{{ if eq .Mode "vxlan" }}{{ .Overlay }}{{ else }}Never{{ end }}"
{{- if eq .Mode "vxlan" }}
- name: FELIX_VXLANPORT
value: "{{ .VxlanPort }}"
- name: FELIX_VXLANVNI
Expand Down
7 changes: 6 additions & 1 deletion docs/networking.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ Kube-router is built into k0s, and so by default the distribution uses it for ne

### Calico

In addition to Kube-router, k0s also offers [Calico] as an alternative, built-in network provider. Calico is a layer 3 container networking solution that routes packets to pods. It supports, for example, pod-specific network policies that help to secure kubernetes clusters in demanding use cases. Calico uses the vxlan overlay network by default, and you can configure it to support ipip (IP-in-IP).
In addition to kube-router, k0s also offers [Calico] as an alternative,
integrated network provider. Calico is a layer 3 container networking solution
that routes packets to pods. For example, it supports pod-specific network
policies that help secure Kubernetes clusters in demanding use cases. Calico in
k0s uses VXLAN by default. However, IP in IP is also supported via the `bird`
mode.

- Uses bit more resources
- Supports Windows nodes
Expand Down
44 changes: 38 additions & 6 deletions pkg/apis/k0s/v1beta1/calico.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ limitations under the License.

package v1beta1

import "encoding/json"
import (
"encoding/json"
"slices"

"k8s.io/apimachinery/pkg/util/validation/field"
)

// Calico defines the calico related config options
type Calico struct {
Expand All @@ -40,11 +45,11 @@ type Calico struct {
// +kubebuilder:default=1450
MTU int `json:"mtu,omitempty"`

// vxlan (default) or ipip
// +kubebuilder:default=vxlan
Mode string `json:"mode,omitempty"`
Mode CalicoMode `json:"mode,omitempty"`

// Overlay Type (Always, Never or CrossSubnet)
// Overlay Type (Always, Never or CrossSubnet).
// Will be ignored in vxlan mode.
// +kubebuilder:default=Always
Overlay string `json:"overlay,omitempty"`

Expand All @@ -57,10 +62,21 @@ type Calico struct {
VxlanVNI int `json:"vxlanVNI,omitempty"`
}

// Indicates the Calico backend to use. Either `bird` or `vxlan`.
// The deprecated legacy value `ipip` is also accepted.
// +kubebuilder:validation:Enum=bird;vxlan;ipip
type CalicoMode string

const (
CalicoModeBIRD CalicoMode = "bird"
CalicoModeVXLAN CalicoMode = "vxlan"
CalicoModeIPIP CalicoMode = "ipip" // Deprecated: Use [CalicoModeBIRD] instead.
)

// DefaultCalico returns sane defaults for calico
func DefaultCalico() *Calico {
return &Calico{
Mode: "vxlan",
Mode: CalicoModeVXLAN,
VxlanPort: 4789,
VxlanVNI: 4096,
MTU: 1450,
Expand All @@ -71,7 +87,7 @@ func DefaultCalico() *Calico {

// UnmarshalJSON sets in some sane defaults when unmarshaling the data from JSON
func (c *Calico) UnmarshalJSON(data []byte) error {
c.Mode = "vxlan"
c.Mode = CalicoModeVXLAN
c.VxlanPort = 4789
c.VxlanVNI = 4096
c.MTU = 1450
Expand All @@ -82,3 +98,19 @@ func (c *Calico) UnmarshalJSON(data []byte) error {
jc := (*calico)(c)
return json.Unmarshal(data, jc)
}

func (c *Calico) Validate(path *field.Path) (errs field.ErrorList) {
if c == nil {
return
}

if c.Mode == "" {
errs = append(errs, field.Required(path.Child("mode"), ""))
} else if allowed := []CalicoMode{
CalicoModeBIRD, CalicoModeVXLAN, CalicoModeIPIP,
}; !slices.Contains(allowed, c.Mode) {
errs = append(errs, field.NotSupported(path.Child("mode"), c.Mode, allowed))
}

return
}
7 changes: 5 additions & 2 deletions pkg/apis/k0s/v1beta1/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ func (n *Network) Validate() []error {
}

if n.DualStack.Enabled {
if n.Provider == "calico" && n.Calico.Mode != "bird" {
errors = append(errors, field.Forbidden(field.NewPath("calico", "mode"), "dual-stack for calico is only supported for mode `bird`"))
if n.Provider == "calico" && n.Calico.Mode != CalicoModeBIRD {
errors = append(errors, field.Forbidden(field.NewPath("calico", "mode"), fmt.Sprintf("dual-stack for calico is only supported for mode `%s`", CalicoModeBIRD)))
}
_, _, err := net.ParseCIDR(n.DualStack.IPv6PodCIDR)
if err != nil {
Expand All @@ -118,6 +118,9 @@ func (n *Network) Validate() []error {
}

errors = append(errors, n.KubeProxy.Validate()...)
for _, err := range n.Calico.Validate(field.NewPath("calico")) {
errors = append(errors, err)
}
for _, err := range n.NodeLocalLoadBalancing.Validate(field.NewPath("nodeLocalLoadBalancing")) {
errors = append(errors, err)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/apis/k0s/v1beta1/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ spec:
s.NotNil(n.Calico)
s.Equal(4789, n.Calico.VxlanPort)
s.Equal(1450, n.Calico.MTU)
s.Equal("vxlan", n.Calico.Mode)
s.Equal(CalicoModeVXLAN, n.Calico.Mode)
}

func (s *NetworkSuite) TestKubeRouterDefaultsAfterMashaling() {
Expand Down Expand Up @@ -244,7 +244,7 @@ func (s *NetworkSuite) TestValidation() {
s.Run("invalid_ipv6_service_cidr", func() {
n := DefaultNetwork()
n.Calico = DefaultCalico()
n.Calico.Mode = "bird"
n.Calico.Mode = CalicoModeBIRD
n.DualStack = DefaultDualStack()
n.DualStack.Enabled = true
n.KubeProxy.Mode = "ipvs"
Expand All @@ -260,7 +260,7 @@ func (s *NetworkSuite) TestValidation() {
s.Run("invalid_ipv6_pod_cidr", func() {
n := DefaultNetwork()
n.Calico = DefaultCalico()
n.Calico.Mode = "bird"
n.Calico.Mode = CalicoModeBIRD
n.DualStack = DefaultDualStack()
n.DualStack.IPv6PodCIDR = "foobar"
n.DualStack.IPv6ServiceCIDR = "fd00::/108"
Expand All @@ -286,7 +286,7 @@ func (s *NetworkSuite) TestValidation() {
s.Run("valid_proxy_disabled_for_dualstack", func() {
n := DefaultNetwork()
n.Calico = DefaultCalico()
n.Calico.Mode = "bird"
n.Calico.Mode = CalicoModeBIRD
n.DualStack = DefaultDualStack()
n.DualStack.Enabled = true
n.KubeProxy.Disabled = true
Expand Down
21 changes: 18 additions & 3 deletions pkg/component/controller/calico.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,20 @@ type Calico struct {
k0sVars *config.CfgVars
}

type calicoMode string

const (
calicoModeBIRD calicoMode = "bird"
calicoModeVXLAN calicoMode = "vxlan"
)

type manifestsSaver interface {
Save(dst string, content []byte) error
}

type calicoConfig struct {
MTU int
Mode string
Mode calicoMode
VxlanPort int
VxlanVNI int
ClusterCIDRIPv4 string
Expand Down Expand Up @@ -186,7 +193,6 @@ func (c *Calico) getConfig(clusterConfig *v1beta1.ClusterConfig) (calicoConfig,
}
config := calicoConfig{
MTU: clusterConfig.Spec.Network.Calico.MTU,
Mode: clusterConfig.Spec.Network.Calico.Mode,
VxlanPort: clusterConfig.Spec.Network.Calico.VxlanPort,
VxlanVNI: clusterConfig.Spec.Network.Calico.VxlanVNI,
EnableWireguard: clusterConfig.Spec.Network.Calico.EnableWireguard,
Expand All @@ -204,6 +210,15 @@ func (c *Calico) getConfig(clusterConfig *v1beta1.ClusterConfig) (calicoConfig,
PullPolicy: clusterConfig.Spec.Images.DefaultPullPolicy,
}

switch clusterConfig.Spec.Network.Calico.Mode {
case v1beta1.CalicoModeBIRD, v1beta1.CalicoModeIPIP:
config.Mode = calicoModeBIRD
case v1beta1.CalicoModeVXLAN:
config.Mode = calicoModeVXLAN
default:
return config, fmt.Errorf("unsupported mode: %q", clusterConfig.Spec.Network.Calico.Mode)
}

return config, nil
}

Expand Down Expand Up @@ -231,7 +246,7 @@ func (c *Calico) Reconcile(_ context.Context, cfg *v1beta1.ClusterConfig) error
})
newConfig, err := c.getConfig(cfg)
if err != nil {
return err
return fmt.Errorf("while generating Calico configuration: %w", err)
}
if !reflect.DeepEqual(newConfig, c.prevConfig) {
if err := c.processConfigChanges(newConfig); err != nil {
Expand Down
24 changes: 17 additions & 7 deletions pkg/component/controller/windowsstackcomponent.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type WindowsStackComponent struct {
type windowsStackRenderingContext struct {
CNIBin string
CNIConf string
Mode string
Mode calicoMode
KubeAPIHost string
KubeAPIPort string
IPv4ServiceCIDR string
Expand Down Expand Up @@ -88,7 +88,7 @@ func (n *WindowsStackComponent) Start(ctx context.Context) error {
case <-ctx.Done():
return
case <-timer.C:
if err := n.handleWindowsNode(ctx, n.prevRenderingContext); err != nil {
if err := n.handleWindowsNode(ctx); err != nil {
n.log.Errorf("failed to handle windows node: %v", err)
}
}
Expand All @@ -98,7 +98,7 @@ func (n *WindowsStackComponent) Start(ctx context.Context) error {
return nil
}

func (n *WindowsStackComponent) handleWindowsNode(ctx context.Context, cfg windowsStackRenderingContext) error {
func (n *WindowsStackComponent) handleWindowsNode(ctx context.Context) error {
client, err := n.kubeClientFactory.GetClient()
if err != nil {
return fmt.Errorf("failed to get kube client: %w", err)
Expand Down Expand Up @@ -136,7 +136,7 @@ func (n *WindowsStackComponent) Reconcile(_ context.Context, cfg *v1beta1.Cluste
}
newConfig, err := n.makeRenderingContext(cfg)
if err != nil {
return fmt.Errorf("failed to make calico rendering context: %w", err)
return fmt.Errorf("while generating Calico configuration: %w", err)
}
if !reflect.DeepEqual(newConfig, n.prevRenderingContext) {
n.prevRenderingContext = newConfig
Expand All @@ -150,19 +150,29 @@ func (n *WindowsStackComponent) makeRenderingContext(cfg *v1beta1.ClusterConfig)
return windowsStackRenderingContext{}, fmt.Errorf("failed to parse dns address: %w", err)
}

return windowsStackRenderingContext{
config := windowsStackRenderingContext{
// template rendering unescapes double backslashes
CNIBin: "c:\\\\opt\\\\cni\\\\bin",
CNIConf: "c:\\\\opt\\\\cni\\\\conf",
Mode: cfg.Spec.Network.Calico.Mode,
KubeAPIHost: cfg.Spec.API.Address,
KubeAPIPort: fmt.Sprintf("%d", cfg.Spec.API.Port),
IPv4ServiceCIDR: cfg.Spec.Network.ServiceCIDR,
Nameserver: dns,
NodeImage: "calico/windows:v3.23.5",
KubeProxyImage: "sigwindowstools/kube-proxy",
KubeProxyVersion: "v1.27.1-calico-hostprocess",
}, nil
}

switch cfg.Spec.Network.Calico.Mode {
case v1beta1.CalicoModeBIRD, v1beta1.CalicoModeIPIP:
config.Mode = calicoModeBIRD
case v1beta1.CalicoModeVXLAN:
config.Mode = calicoModeVXLAN
default:
return config, fmt.Errorf("unsupported mode: %q", cfg.Spec.Network.Calico.Mode)
}

return config, nil
}

// Stop no-op
Expand Down
12 changes: 10 additions & 2 deletions static/_crds/k0s/k0s.k0sproject.io_clusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -447,15 +447,23 @@ spec:
type: string
mode:
default: vxlan
description: vxlan (default) or ipip
description: |-
Indicates the Calico backend to use. Either `bird` or `vxlan`.
The deprecated legacy value `ipip` is also accepted.
enum:
- bird
- vxlan
- ipip
type: string
mtu:
default: 1450
description: 'MTU for overlay network (default: 1450)'
type: integer
overlay:
default: Always
description: Overlay Type (Always, Never or CrossSubnet)
description: |-
Overlay Type (Always, Never or CrossSubnet).
Will be ignored in vxlan mode.
type: string
vxlanPort:
default: 4789
Expand Down
15 changes: 4 additions & 11 deletions static/manifests/calico/DaemonSet/calico-node.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,16 @@ spec:
- name: IP6_AUTODETECTION_METHOD
value: {{ .IPV6AutodetectionMethod }}
{{ end }}
{{- if eq .Mode "ipip" }}
# Enable IPIP
- name: CALICO_IPV4POOL_IPIP
value: {{ .Overlay }}
value: "{{ if eq .Mode "bird" }}{{ .Overlay }}{{ else }}Never{{ end }}"
# Enable or Disable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: "Never"
value: "{{ if eq .Mode "vxlan" }}{{ .Overlay }}{{ else }}Never{{ end }}"
# Enable or Disable VXLAN on the default IPv6 IP pool.
- name: CALICO_IPV6POOL_VXLAN
value: "Never"
{{- else if eq .Mode "vxlan" }}
# Disable IPIP
- name: CALICO_IPV4POOL_IPIP
value: "Never"
# Enable VXLAN on the default IP pool.
- name: CALICO_IPV4POOL_VXLAN
value: {{ .Overlay }}
value: "{{ if eq .Mode "vxlan" }}{{ .Overlay }}{{ else }}Never{{ end }}"
{{- if eq .Mode "vxlan" }}
- name: FELIX_VXLANPORT
value: "{{ .VxlanPort }}"
- name: FELIX_VXLANVNI
Expand Down
Loading