diff --git a/api/pkg/apis/projectcalico/v3/felixconfig.go b/api/pkg/apis/projectcalico/v3/felixconfig.go index 755212cd082..8d33bb105fb 100644 --- a/api/pkg/apis/projectcalico/v3/felixconfig.go +++ b/api/pkg/apis/projectcalico/v3/felixconfig.go @@ -63,6 +63,13 @@ const ( NFTablesModeDisabled = "Disabled" ) +type ProgramRouteMode string + +const ( + ProgramRouteModeNone ProgramRouteMode = "None" + ProgramRouteModeIPIP ProgramRouteMode = "IPIP" +) + // +kubebuilder:validation:Enum=DoNothing;Enable;Disable type AWSSrcDstCheckOption string @@ -324,6 +331,8 @@ type FelixConfigurationSpec struct { // IPIPMTU controls the MTU to set on the IPIP tunnel device. Optional as Felix auto-detects the MTU based on the // MTU of the host's interfaces. [Default: 0 (auto-detect)] IPIPMTU *int `json:"ipipMTU,omitempty" confignamev1:"IpInIpMtu"` + // ProgramRoutes specifies what type of routes Felix should program. [Default: None]. [Default: None] + ProgramRoutes *ProgramRouteMode `json:"programRoutes,omitempty" validate:"omitempty,oneof=None IPIP"` // VXLANEnabled overrides whether Felix should create the VXLAN tunnel device for IPv4 VXLAN networking. // Optional as Felix determines this based on the existing IP pools. [Default: nil (unset)] diff --git a/api/pkg/apis/projectcalico/v3/zz_generated.deepcopy.go b/api/pkg/apis/projectcalico/v3/zz_generated.deepcopy.go index 273d69857af..fe8273af68c 100644 --- a/api/pkg/apis/projectcalico/v3/zz_generated.deepcopy.go +++ b/api/pkg/apis/projectcalico/v3/zz_generated.deepcopy.go @@ -1211,6 +1211,11 @@ func (in *FelixConfigurationSpec) DeepCopyInto(out *FelixConfigurationSpec) { *out = new(int) **out = **in } + if in.ProgramRoutes != nil { + in, out := &in.ProgramRoutes, &out.ProgramRoutes + *out = new(ProgramRouteMode) + **out = **in + } if in.VXLANEnabled != nil { in, out := &in.VXLANEnabled, &out.VXLANEnabled *out = new(bool) diff --git a/api/pkg/openapi/generated.openapi.go b/api/pkg/openapi/generated.openapi.go index ef1ed3895c6..e6f4fad666c 100644 --- a/api/pkg/openapi/generated.openapi.go +++ b/api/pkg/openapi/generated.openapi.go @@ -2608,6 +2608,13 @@ func schema_pkg_apis_projectcalico_v3_FelixConfigurationSpec(ref common.Referenc Format: "int32", }, }, + "programRoutes": { + SchemaProps: spec.SchemaProps{ + Description: "ProgramRoutes specifies what type of routes Felix should program. [Default: None]. [Default: None]", + Type: []string{"string"}, + Format: "", + }, + }, "vxlanEnabled": { SchemaProps: spec.SchemaProps{ Description: "VXLANEnabled overrides whether Felix should create the VXLAN tunnel device for IPv4 VXLAN networking. Optional as Felix determines this based on the existing IP pools. [Default: nil (unset)]", diff --git a/charts/calico/templates/calico-config.yaml b/charts/calico/templates/calico-config.yaml index 6b00f53649b..fd00e37a44d 100644 --- a/charts/calico/templates/calico-config.yaml +++ b/charts/calico/templates/calico-config.yaml @@ -41,6 +41,8 @@ data: # Configure the backend to use. {{- if or (.Values.flannel_migration) (.Values.vxlan) }} calico_backend: "vxlan" +{{- else if (.Values.ipip) }} + calico_backend: "ipip" {{- else }} calico_backend: "bird" {{- end }} diff --git a/charts/calico/templates/calico-node.yaml b/charts/calico/templates/calico-node.yaml index 58b5e548d21..5200252d1bf 100644 --- a/charts/calico/templates/calico-node.yaml +++ b/charts/calico/templates/calico-node.yaml @@ -323,6 +323,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "{{- if .Values.vxlan -}} CrossSubnet {{- else -}} Never {{- end -}}" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "{{ if .Values.ipip -}} IPIP {{- else -}} None {{- end -}}" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: @@ -406,7 +409,7 @@ spec: command: - /bin/calico-node - -felix-live -{{- if and (eq .Values.network "calico") (not .Values.flannel_migration) (not .Values.vxlan) }} +{{- if and (eq .Values.network "calico") (not .Values.flannel_migration) (not .Values.vxlan) (not .Values.ipip) }} - -bird-live {{- end }} periodSeconds: 10 @@ -419,7 +422,7 @@ spec: command: - /bin/calico-node - -felix-ready -{{- if and (not .Values.flannel_migration) (not .Values.vxlan) }} +{{- if and (not .Values.flannel_migration) (not .Values.vxlan) (not .Values.ipip) }} - -bird-ready {{- end }} {{- else if eq .Values.network "flannel" }} diff --git a/charts/values/calico-ipip.yaml b/charts/values/calico-ipip.yaml new file mode 100644 index 00000000000..603289215e6 --- /dev/null +++ b/charts/values/calico-ipip.yaml @@ -0,0 +1,3 @@ +datastore: kubernetes +network: calico +ipip: true diff --git a/felix/calc/calc_graph.go b/felix/calc/calc_graph.go index 66c0053cbc3..47323940230 100644 --- a/felix/calc/calc_graph.go +++ b/felix/calc/calc_graph.go @@ -392,7 +392,8 @@ func NewCalculationGraph( hostIPPassthru.RegisterWith(allUpdDispatcher) cg.hostIPPassthru = hostIPPassthru - if conf.BPFEnabled || conf.Encapsulation.VXLANEnabled || conf.Encapsulation.VXLANEnabledV6 || conf.WireguardEnabled || conf.WireguardEnabledV6 { + if conf.BPFEnabled || conf.Encapsulation.VXLANEnabled || conf.Encapsulation.VXLANEnabledV6 || + conf.WireguardEnabled || conf.WireguardEnabledV6 || conf.ProgramIPIPRoutes() { // Calculate simple node-ownership routes. // ... // Dispatcher (all updates) diff --git a/felix/config/config_params.go b/felix/config/config_params.go index 002b43718cd..cfab0e1d1cc 100644 --- a/felix/config/config_params.go +++ b/felix/config/config_params.go @@ -353,6 +353,7 @@ type Config struct { IpInIpEnabled *bool `config:"*bool;"` IpInIpMtu int `config:"int;0"` IpInIpTunnelAddr net.IP `config:"ipv4;"` + ProgramRoutes string `config:"oneof(None,IPIP);None"` // Feature enablement. Can be either "Enabled" or "Disabled". Note, this governs the // programming of NAT mappings derived from Kubernetes pod annotations. OpenStack floating @@ -1241,6 +1242,10 @@ func (config *Config) RouteTableIndices() []idalloc.IndexRange { return config.RouteTableRanges } +func (config *Config) ProgramIPIPRoutes() bool { + return config.ProgramRoutes == string(v3.ProgramRouteModeIPIP) +} + func New() *Config { if knownParams == nil { loadParams() diff --git a/felix/dataplane/driver.go b/felix/dataplane/driver.go index b49fb078191..69c3dece274 100644 --- a/felix/dataplane/driver.go +++ b/felix/dataplane/driver.go @@ -310,6 +310,7 @@ func StartDataplaneDriver( RouteSyncDisabled: configParams.RouteSyncDisabled, }, IPIPMTU: configParams.IpInIpMtu, + ProgramIPIPRoutes: configParams.ProgramIPIPRoutes(), VXLANMTU: configParams.VXLANMTU, VXLANMTUV6: configParams.VXLANMTUV6, VXLANPort: configParams.VXLANPort, diff --git a/felix/dataplane/linux/bpf_ep_mgr.go b/felix/dataplane/linux/bpf_ep_mgr.go index fc60474fc05..32a122bdea9 100644 --- a/felix/dataplane/linux/bpf_ep_mgr.go +++ b/felix/dataplane/linux/bpf_ep_mgr.go @@ -549,7 +549,11 @@ func newBPFEndpointManager( specialInterfaces := []string{"egress.calico"} if config.RulesConfig.IPIPEnabled { - specialInterfaces = append(specialInterfaces, dataplanedefs.IPIPIfaceName) + if config.ProgramIPIPRoutes { + specialInterfaces = append(specialInterfaces, dataplanedefs.IPIPIfaceNameV4) + } else { + specialInterfaces = append(specialInterfaces, dataplanedefs.IPIPDefaultIfaceNameV4) + } } if config.RulesConfig.VXLANEnabled { specialInterfaces = append(specialInterfaces, dataplanedefs.VXLANIfaceNameV4) diff --git a/felix/dataplane/linux/dataplanedefs/dataplane_defs.go b/felix/dataplane/linux/dataplanedefs/dataplane_defs.go index 9c3ad4cc4a5..20eed7f729f 100644 --- a/felix/dataplane/linux/dataplanedefs/dataplane_defs.go +++ b/felix/dataplane/linux/dataplanedefs/dataplane_defs.go @@ -17,10 +17,13 @@ package dataplanedefs import "github.com/vishvananda/netlink" const ( - IPIPIfaceName = "tunl0" - VXLANIfaceNameV4 = "vxlan.calico" - VXLANIfaceNameV6 = "vxlan-v6.calico" - VXLANDefaultProto netlink.RouteProtocol = 80 + VXLANIfaceNameV4 = "vxlan.calico" + VXLANIfaceNameV6 = "vxlan-v6.calico" + + IPIPIfaceNameV4 = "ipip.calico" + IPIPDefaultIfaceNameV4 = "tunl0" + + DefaultRoutingProto netlink.RouteProtocol = 80 BPFInDev = "bpfin.cali" BPFOutDev = "bpfout.cali" diff --git a/felix/dataplane/linux/int_dataplane.go b/felix/dataplane/linux/int_dataplane.go index 1bfd4fd4d79..be236f9e8d2 100644 --- a/felix/dataplane/linux/int_dataplane.go +++ b/felix/dataplane/linux/int_dataplane.go @@ -149,10 +149,13 @@ type Config struct { NodeZone string IPv6Enabled bool RuleRendererOverride rules.RuleRenderer - IPIPMTU int - VXLANMTU int - VXLANMTUV6 int - VXLANPort int + + IPIPMTU int + ProgramIPIPRoutes bool + + VXLANMTU int + VXLANMTUV6 int + VXLANPort int MaxIPSetSize int @@ -319,6 +322,7 @@ type InternalDataplane struct { ipSets []dpsets.IPSetsDataplane ipipManager *ipipManager + ipipParentC chan string vxlanManager *vxlanManager vxlanParentC chan string @@ -1035,10 +1039,33 @@ func NewIntDataplaneDriver(config Config) *InternalDataplane { dp.RegisterManager(newFloatingIPManager(natTableV4, ruleRenderer, 4, config.FloatingIPsEnabled)) dp.RegisterManager(newMasqManager(ipSetsV4, natTableV4, ruleRenderer, config.MaxIPSetSize, 4)) if config.RulesConfig.IPIPEnabled { - log.Info("IPIP enabled, starting thread to keep tunnel configuration in sync.") - // Add a manager to keep the all-hosts IP set up to date. - dp.ipipManager = newIPIPManager(ipSetsV4, config.MaxIPSetSize, config.ExternalNodesCidrs) - go dp.ipipManager.KeepIPIPDeviceInSync(config.IPIPMTU, config.RulesConfig.IPIPTunnelAddress, dataplaneFeatures.ChecksumOffloadBroken) + if config.ProgramIPIPRoutes { + log.Info("IPIP enabled, starting thread to keep tunnel configuration in sync.") + // Add a manager to keep the all-hosts IP set up to date. + dp.ipipManager = newIPIPManager( + ipSetsV4, + routeTableV4, + dataplanedefs.IPIPIfaceNameV4, + config, + dp.loopSummarizer, + 4, + featureDetector, + ) + dp.ipipParentC = make(chan string, 1) + go dp.ipipManager.KeepCalicoIPIPDeviceInSync(context.Background(), dataplaneFeatures.ChecksumOffloadBroken, 10*time.Second, dp.ipipParentC) + } else { + log.Info("IPIP using BGP enabled, starting thread to keep tunnel configuration in sync.") + dp.ipipManager = newIPIPManager( + ipSetsV4, + nil, + dataplanedefs.IPIPDefaultIfaceNameV4, + config, + dp.loopSummarizer, + 4, + featureDetector, + ) + go dp.ipipManager.KeepIPIPDeviceInSync(dataplaneFeatures.ChecksumOffloadBroken) + } dp.RegisterManager(dp.ipipManager) // IPv4-only } else { // Only clean up IPIP addresses if IPIP is implicitly disabled (no IPIP pools and not explicitly set in FelixConfig) @@ -2078,6 +2105,8 @@ func (d *InternalDataplane) loopUpdatingDataplane() { d.vxlanManager.OnParentNameUpdate(name) case name := <-d.vxlanParentCV6: d.vxlanManagerV6.OnParentNameUpdate(name) + case name := <-d.ipipParentC: + d.ipipManager.OnParentNameUpdate(name) case <-ipSetsRefreshC: log.Debug("Refreshing IP sets state") d.forceIPSetsRefresh = true diff --git a/felix/dataplane/linux/ipip_mgr.go b/felix/dataplane/linux/ipip_mgr.go index 36ef82c543a..5f0933e5db8 100644 --- a/felix/dataplane/linux/ipip_mgr.go +++ b/felix/dataplane/linux/ipip_mgr.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2024 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,17 +15,28 @@ package intdataplane import ( + "context" + "errors" "fmt" "net" + "sync" + "syscall" "time" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" dpsets "github.com/projectcalico/calico/felix/dataplane/ipsets" + "github.com/projectcalico/calico/felix/dataplane/linux/dataplanedefs" + "github.com/projectcalico/calico/felix/environment" "github.com/projectcalico/calico/felix/ethtool" + "github.com/projectcalico/calico/felix/ip" "github.com/projectcalico/calico/felix/ipsets" + "github.com/projectcalico/calico/felix/logutils" + "github.com/projectcalico/calico/felix/netlinkshim" "github.com/projectcalico/calico/felix/proto" + "github.com/projectcalico/calico/felix/routetable" "github.com/projectcalico/calico/felix/rules" ) @@ -35,57 +46,434 @@ import ( // // ipipManager also takes care of the configuration of the IPIP tunnel device. type ipipManager struct { - ipsetsDataplane dpsets.IPSetsDataplane + // Our dependencies. + routeTable routetable.Interface + parentIfaceName string - // activeHostnameToIP maps hostname to string IP address. We don't bother to parse into + // activeHostnameToIP maps hostname to string IP address. We don't bother to parse into // net.IPs because we're going to pass them directly to the IPSet API. activeHostnameToIP map[string]string - ipSetInSync bool + ipSetDirty bool + ipsetsDataplane dpsets.IPSetsDataplane - // Config for creating/refreshing the IP set. - ipSetMetadata ipsets.IPSetMetadata + // Hold pending updates. + routesByDest map[string]*proto.RouteUpdate + localIPAMBlocks map[string]*proto.RouteUpdate + + // IPIP configuration. + ipipDevice string + ipVersion uint8 - // Dataplane shim. - dataplane ipipDataplane + // Local information + hostname string + hostAddr string + myAddrLock sync.Mutex + myAddrChangedC chan struct{} + // Indicates if configuration has changed since the last apply. + routesDirty bool + // Config for creating/refreshing the IP set. + ipSetMetadata ipsets.IPSetMetadata // Configured list of external node ip cidr's to be added to the ipset. externalNodeCIDRs []string + nlHandle netlinkHandle + dpConfig Config + routeProtocol netlink.RouteProtocol + + // Log context + logCtx *logrus.Entry + opRecorder logutils.OpRecorder } func newIPIPManager( ipsetsDataplane dpsets.IPSetsDataplane, - maxIPSetSize int, - externalNodeCidrs []string, + mainRouteTable routetable.Interface, + deviceName string, + dpConfig Config, + opRecorder logutils.OpRecorder, + ipVersion uint8, + featureDetector environment.FeatureDetectorIface, ) *ipipManager { - return newIPIPManagerWithShim(ipsetsDataplane, maxIPSetSize, realIPIPNetlink{}, externalNodeCidrs) + nlHandle, _ := netlinkshim.NewRealNetlink() + return newIPIPManagerWithShim( + ipsetsDataplane, + mainRouteTable, + deviceName, + dpConfig, + opRecorder, + nlHandle, + ipVersion, + ) } func newIPIPManagerWithShim( ipsetsDataplane dpsets.IPSetsDataplane, - maxIPSetSize int, - dataplane ipipDataplane, - externalNodeCIDRs []string, + mainRouteTable routetable.Interface, + deviceName string, + dpConfig Config, + opRecorder logutils.OpRecorder, + nlHandle netlinkHandle, + ipVersion uint8, ) *ipipManager { - ipipMgr := &ipipManager{ + if ipVersion != 4 { + logrus.Errorf("IPIP manager only supports IPv4") + return nil + } + return &ipipManager{ ipsetsDataplane: ipsetsDataplane, activeHostnameToIP: map[string]string{}, - dataplane: dataplane, + myAddrChangedC: make(chan struct{}, 1), ipSetMetadata: ipsets.IPSetMetadata{ - MaxSize: maxIPSetSize, + MaxSize: dpConfig.MaxIPSetSize, SetID: rules.IPSetIDAllHostNets, Type: ipsets.IPSetTypeHashNet, }, - externalNodeCIDRs: externalNodeCIDRs, + hostname: dpConfig.Hostname, + routeTable: mainRouteTable, + routesByDest: map[string]*proto.RouteUpdate{}, + localIPAMBlocks: map[string]*proto.RouteUpdate{}, + ipipDevice: deviceName, + ipVersion: ipVersion, + externalNodeCIDRs: dpConfig.ExternalNodesCidrs, + routesDirty: true, + ipSetDirty: true, + dpConfig: dpConfig, + nlHandle: nlHandle, + routeProtocol: calculateRouteProtocol(dpConfig), + logCtx: logrus.WithField("ipVersion", ipVersion), + opRecorder: opRecorder, + } +} + +func (m *ipipManager) OnUpdate(msg interface{}) { + switch msg := msg.(type) { + case *proto.RouteUpdate: + cidr, err := ip.CIDRFromString(msg.Dst) + if err != nil { + m.logCtx.WithError(err).WithField("msg", msg).Warning("Unable to parse route update destination. Skipping update.") + return + } + if m.ipVersion != cidr.Version() { + // Skip since the update is for a mismatched IP version + return + } + + // In case the route changes type to one we no longer care about... + m.deleteRoute(msg.Dst) + + // Process remote IPAM blocks. + if msg.Type == proto.RouteType_REMOTE_WORKLOAD && msg.IpPoolType == proto.IPPoolType_IPIP { + m.logCtx.WithField("msg", msg).Debug("IPIP data plane received route update") + m.routesByDest[msg.Dst] = msg + m.routesDirty = true + } + + // Process IPAM blocks that aren't associated to a single or /32 local workload + if routeIsLocalBlock(msg, proto.IPPoolType_IPIP) { + m.logCtx.WithField("msg", msg).Debug("IPIP data plane received route update for IPAM block") + m.localIPAMBlocks[msg.Dst] = msg + m.routesDirty = true + } else if _, ok := m.localIPAMBlocks[msg.Dst]; ok { + m.logCtx.WithField("msg", msg).Debug("IPIP data plane IPAM block changed to something else") + delete(m.localIPAMBlocks, msg.Dst) + m.routesDirty = true + } + + case *proto.RouteRemove: + // Check to make sure that we are dealing with messages of the correct IP version. + cidr, err := ip.CIDRFromString(msg.Dst) + if err != nil { + m.logCtx.WithError(err).WithField("msg", msg).Warning("Unable to parse route removal destination. Skipping update.") + return + } + if m.ipVersion != cidr.Version() { + // Skip since the update is for a mismatched IP version + return + } + m.deleteRoute(msg.Dst) + case *proto.HostMetadataUpdate: + m.logCtx.WithField("hostname", msg.Hostname).Debug("Host update/create") + if msg.Hostname == m.hostname { + m.setLocalHostAddr(msg.Ipv4Addr) + } + m.activeHostnameToIP[msg.Hostname] = msg.Ipv4Addr + m.ipSetDirty = true + m.routesDirty = true + case *proto.HostMetadataRemove: + m.logCtx.WithField("hostname", msg.Hostname).Debug("Host removed") + if msg.Hostname == m.hostname { + m.setLocalHostAddr("") + } + delete(m.activeHostnameToIP, msg.Hostname) + m.ipSetDirty = true + m.routesDirty = true + } +} + +func (m *ipipManager) deleteRoute(dst string) { + _, exists := m.routesByDest[dst] + if exists { + logrus.Debug("deleting route dst ", dst) + // In case the route changes type to one we no longer care about... + delete(m.routesByDest, dst) + m.routesDirty = true + } + + if _, exists := m.localIPAMBlocks[dst]; exists { + logrus.Debug("deleting local ipam dst ", dst) + delete(m.localIPAMBlocks, dst) + m.routesDirty = true + } +} + +func (m *ipipManager) setLocalHostAddr(address string) { + m.myAddrLock.Lock() + defer m.myAddrLock.Unlock() + m.hostAddr = address + select { + case m.myAddrChangedC <- struct{}{}: + default: + } +} + +func (m *ipipManager) getLocalHostAddr() string { + m.myAddrLock.Lock() + defer m.myAddrLock.Unlock() + return m.hostAddr +} + +func (m *ipipManager) CompleteDeferredWork() error { + if m.ipSetDirty { + m.updateAllHostsIPSet() + m.ipSetDirty = false + } + // Program IPIP routes, only if ProgramIPIPRoutes is true + if !m.dpConfig.ProgramIPIPRoutes { + m.routesDirty = false + return nil + } + if m.parentIfaceName == "" { + // Background goroutine hasn't sent us the parent interface name yet, + // but we can look it up synchronously. OnParentNameUpdate will handle + // any duplicate update when it arrives. + parent, err := m.getParentInterface() + if err != nil { + // If we can't look up the parent interface then we're in trouble. + // It likely means that our local address is missing or conflicting. We + // won't be able to program same-subnet routes at all, so we'll + // fall back to programming all tunnel routes. However, unless the + // ipip device happens to already exist, we won't be able to + // program tunnel routes either. The RouteTable will be the + // component that spots that the interface is missing. + // + // Note: this behaviour changed when we unified all the main + // RouteTable instances into one. Before that change, we chose to + // defer creation of our "no encap" RouteTable, so that the + // dataplane would stay untouched until the conflict was resolved. + // With only a single RouteTable, we need a different fallback. + m.logCtx.WithError(err).WithField("local address", m.getLocalHostAddr()).Error( + "Failed to find ipip tunnel device parent. Missing/conflicting local address? ipip route " + + "programming is likely to fail.") + } else { + m.parentIfaceName = parent.Attrs().Name + m.routesDirty = true + } + } + if m.routesDirty { + err := m.updateRoutes() + if err != nil { + return err + } + m.routesDirty = false + } + m.logCtx.Info("IPIP Manager completed deferred work") + return nil +} + +func (m *ipipManager) updateAllHostsIPSet() { + // For simplicity (and on the assumption that host add/removes are rare) rewrite + // the whole IP set whenever we get a change. To replace this with delta handling + // would require reference counting the IPs because it's possible for two hosts + // to (at least transiently) share an IP. That would add occupancy and make the + // code more complex. + m.logCtx.Info("All-hosts IP set out-of sync, refreshing it.") + members := make([]string, 0, len(m.activeHostnameToIP)+len(m.externalNodeCIDRs)) + for _, ip := range m.activeHostnameToIP { + members = append(members, ip) + } + members = append(members, m.externalNodeCIDRs...) + m.ipsetsDataplane.AddOrReplaceIPSet(m.ipSetMetadata, members) +} + +func (m *ipipManager) updateRoutes() error { + // Iterate through all of our L3 routes and send them through to the + // RouteTable. It's a little wasteful to recalculate everything but the + // RouteTable will avoid making dataplane changes for routes that haven't + // changed. + m.opRecorder.RecordOperation("update-ipip-routes") + + var ipipRoutes []routetable.Target + var noEncapRoutes []routetable.Target + for _, r := range m.routesByDest { + logCtx := m.logCtx.WithField("route", r) + cidr, err := ip.CIDRFromString(r.Dst) + if err != nil { + // Don't block programming of other routes if somehow we receive one with a bad dst. + logCtx.WithError(err).Warn("Failed to parse IPIP route destination") + continue + } + + if noEncapRoute := noEncapRoute(m.parentIfaceName, cidr, r, m.routeProtocol); noEncapRoute != nil { + // We've got everything we need to program this route as a no-encap route. + noEncapRoutes = append(noEncapRoutes, *noEncapRoute) + logCtx.WithField("route", r).Debug("Destination in same subnet, using no-encap route.") + } else if ipipRoute := m.tunneledRoute(cidr, r); ipipRoute != nil { + ipipRoutes = append(ipipRoutes, *ipipRoute) + logCtx.WithField("route", ipipRoute).Debug("adding ipip route to list for addition") + } else { + logCtx.Debug("Not enough information to program route; missing target host address?") + } + } + + m.logCtx.WithField("ipipRoutes", ipipRoutes).Debug("IPIP manager setting IPIP tunnled routes") + m.routeTable.SetRoutes(routetable.RouteClassIPIPTTunnel, m.ipipDevice, ipipRoutes) + + bhRoutes := blackholeRoutes(m.localIPAMBlocks, m.routeProtocol) + m.logCtx.WithField("balckholes", bhRoutes).Debug("IPIP manager setting blackhole routes") + m.routeTable.SetRoutes(routetable.RouteClassIPAMBlockDrop, routetable.InterfaceNone, bhRoutes) + + if m.parentIfaceName != "" { + m.logCtx.WithFields(logrus.Fields{ + "noEncapDevice": m.parentIfaceName, + "routes": noEncapRoutes, + }).Debug("IPIP manager sending unencapsulated L3 updates") + m.routeTable.SetRoutes(routetable.RouteClassIPIPTSameSubnet, m.parentIfaceName, noEncapRoutes) + } else { + return errors.New("no encap route table not set, will defer adding routes") + } + + return nil +} + +func (m *ipipManager) tunneledRoute(cidr ip.CIDR, r *proto.RouteUpdate) *routetable.Target { + // Extract the gateway addr for this route based on its remote address. + remoteAddr, ok := m.activeHostnameToIP[r.DstNodeName] + if !ok { + // When the local address arrives, it'll set routesDirty=true so this loop will execute again. + return nil } - return ipipMgr + + ipipRoute := routetable.Target{ + Type: routetable.TargetTypeOnLink, + CIDR: cidr, + GW: ip.FromString(remoteAddr), + Protocol: m.routeProtocol, + } + return &ipipRoute +} + +func (m *ipipManager) OnParentNameUpdate(name string) { + if name == "" { + m.logCtx.Warn("Empty parent interface name? Ignoring.") + return + } + if name == m.parentIfaceName { + return + } + if m.parentIfaceName != "" { + // We're changing parent interface, remove the old routes. + m.routeTable.SetRoutes(routetable.RouteClassIPIPTSameSubnet, m.parentIfaceName, nil) + } + m.parentIfaceName = name + m.routesDirty = true } // KeepIPIPDeviceInSync is a goroutine that configures the IPIP tunnel device, then periodically // checks that it is still correctly configured. -func (d *ipipManager) KeepIPIPDeviceInSync(mtu int, address net.IP, xsumBroken bool) { - log.Info("IPIP thread started.") +func (m *ipipManager) KeepCalicoIPIPDeviceInSync( + ctx context.Context, + xsumBroken bool, + wait time.Duration, + parentNameC chan string, +) { + mtu := m.dpConfig.IPIPMTU + address := m.dpConfig.RulesConfig.IPIPTunnelAddress + m.logCtx.WithFields(logrus.Fields{ + "device": m.ipipDevice, + "mtu": mtu, + "xsumBroken": xsumBroken, + "wait": wait, + }).Info("IPIP device thread started.") + logNextSuccess := true + parentName := "" + + sleepMonitoringChans := func(maxDuration time.Duration) { + timer := time.NewTimer(maxDuration) + defer timer.Stop() + select { + case <-timer.C: + case <-ctx.Done(): + logrus.Debug("Sleep returning early: context finished.") + case <-m.myAddrChangedC: + logrus.Debug("Sleep returning early: local address changed.") + } + } + + for ctx.Err() == nil { + localAddr := m.getLocalHostAddr() + if localAddr == "" { + m.logCtx.Debug("Missing local address information, retrying...") + sleepMonitoringChans(10 * time.Second) + continue + } + + parent, err := m.getParentInterface() + if err != nil { + m.logCtx.WithError(err).Warn("Failed to find IPIP tunnel device parent, retrying...") + sleepMonitoringChans(1 * time.Second) + continue + } + + m.logCtx.WithField("localAddr", address).Debug("Configuring IPIP device") + err = m.configureIPIPDevice(mtu, address, xsumBroken) + if err != nil { + m.logCtx.WithError(err).Warn("Failed to configure IPIP tunnel device, retrying...") + logNextSuccess = true + sleepMonitoringChans(1 * time.Second) + continue + } + + newParentName := parent.Attrs().Name + if newParentName != parentName { + // Send a message back to the main loop to tell it to update the + // routing tables. + m.logCtx.Infof("IPIP device parent changed from %q to %q", parentName, newParentName) + select { + case parentNameC <- newParentName: + parentName = newParentName + case <-m.myAddrChangedC: + m.logCtx.Info("My address changed; restarting configuration.") + continue + case <-ctx.Done(): + continue + } + } + + if logNextSuccess { + m.logCtx.Info("IPIP tunnel device configured") + logNextSuccess = false + } + sleepMonitoringChans(wait) + } + m.logCtx.Info("KeepIPIPDeviceInSync exiting due to context.") +} + +// KeepIPIPDeviceInSync is a goroutine that configures the IPIP tunnel device, then periodically +// checks that it is still correctly configured. +func (m *ipipManager) KeepIPIPDeviceInSync(xsumBroken bool) { + log.WithField("device", m.ipipDevice).Info("IPIP device thread started.") for { - err := d.configureIPIPDevice(mtu, address, xsumBroken) + err := m.configureIPIPDevice(m.dpConfig.IPIPMTU, m.dpConfig.RulesConfig.IPIPTunnelAddress, xsumBroken) if err != nil { log.WithError(err).Warn("Failed configure IPIP tunnel device, retrying...") time.Sleep(1 * time.Second) @@ -95,27 +483,77 @@ func (d *ipipManager) KeepIPIPDeviceInSync(mtu int, address net.IP, xsumBroken b } } +// getParentInterface returns the parent interface for the given local address. This link returned is nil +// if, and only if, an error occurred +func (m *ipipManager) getParentInterface() (netlink.Link, error) { + localAddr := m.getLocalHostAddr() + if localAddr == "" { + return nil, fmt.Errorf("local address not found") + } + + m.logCtx.WithField("local address", localAddr).Debug("Getting parent interface") + links, err := m.nlHandle.LinkList() + if err != nil { + return nil, err + } + + for _, link := range links { + addrs, err := m.nlHandle.AddrList(link, netlink.FAMILY_V4) + if err != nil { + return nil, err + } + for _, addr := range addrs { + if addr.IPNet.IP.String() == localAddr { + m.logCtx.Debugf("Found parent interface: %s", link) + return link, nil + } + } + } + return nil, fmt.Errorf("Unable to find parent interface with address %s", localAddr) +} + // configureIPIPDevice ensures the IPIP tunnel device is up and configures correctly. -func (d *ipipManager) configureIPIPDevice(mtu int, address net.IP, xsumBroken bool) error { +func (m *ipipManager) configureIPIPDevice(mtu int, address net.IP, xsumBroken bool) error { logCxt := log.WithFields(log.Fields{ "mtu": mtu, "tunnelAddr": address, + "device": m.ipipDevice, }) logCxt.Debug("Configuring IPIP tunnel") - link, err := d.dataplane.LinkByName("tunl0") + + la := netlink.NewLinkAttrs() + la.Name = m.ipipDevice + ipip := &netlink.Iptun{ + LinkAttrs: la, + } + + if m.ipipDevice == dataplanedefs.IPIPIfaceNameV4 { + localAddr := m.getLocalHostAddr() + localIP := net.ParseIP(localAddr) + if localIP == nil { + return fmt.Errorf("invalid address %v", localAddr) + } + ipip.Local = localIP + } + + link, err := m.nlHandle.LinkByName(m.ipipDevice) if err != nil { - log.WithError(err).Info("Failed to get IPIP tunnel device, assuming it isn't present") + m.logCtx.WithError(err).Info("Failed to get IPIP tunnel device, assuming it isn't present") + // We call out to "ip tunnel", which takes care of loading the kernel module if // needed. The tunl0 device is actually created automatically by the kernel // module. - err := d.dataplane.RunCmd("ip", "tunnel", "add", "tunl0", "mode", "ipip") - if err != nil { - log.WithError(err).Warning("Failed to add IPIP tunnel device") + if err := m.nlHandle.LinkAdd(ipip); err == syscall.EEXIST { + // Device already exists - likely a race. + m.logCtx.Debug("IPIP device already exists, likely created by someone else.") + } else if err != nil { + // Error other than "device exists" - return it. return err } - link, err = d.dataplane.LinkByName("tunl0") + + link, err = m.nlHandle.LinkByName(m.ipipDevice) if err != nil { - log.WithError(err).Warning("Failed to get tunnel device") + m.logCtx.WithError(err).Warning("Failed to get tunnel device") return err } } @@ -124,8 +562,8 @@ func (d *ipipManager) configureIPIPDevice(mtu int, address net.IP, xsumBroken bo oldMTU := attrs.MTU if oldMTU != mtu { logCxt.WithField("oldMTU", oldMTU).Info("Tunnel device MTU needs to be updated") - if err := d.dataplane.LinkSetMTU(link, mtu); err != nil { - log.WithError(err).Warn("Failed to set tunnel device MTU") + if err := m.nlHandle.LinkSetMTU(link, mtu); err != nil { + m.logCtx.WithError(err).Warn("Failed to set tunnel device MTU") return err } logCxt.Info("Updated tunnel MTU") @@ -133,22 +571,26 @@ func (d *ipipManager) configureIPIPDevice(mtu int, address net.IP, xsumBroken bo // If required, disable checksum offload. if xsumBroken { - if err := ethtool.EthtoolTXOff("tunl0"); err != nil { + if err := ethtool.EthtoolTXOff(m.ipipDevice); err != nil { return fmt.Errorf("failed to disable checksum offload: %s", err) } } if attrs.Flags&net.FlagUp == 0 { logCxt.WithField("flags", attrs.Flags).Info("Tunnel wasn't admin up, enabling it") - if err := d.dataplane.LinkSetUp(link); err != nil { - log.WithError(err).Warn("Failed to set tunnel device up") + if err := m.nlHandle.LinkSetUp(link); err != nil { + m.logCtx.WithError(err).Warn("Failed to set tunnel device up") return err } logCxt.Info("Set tunnel admin up") } + // And the device is up. + /*if err := m.nlHandle.LinkSetUp(link); err != nil { + return fmt.Errorf("failed to set interface up: %s", err) + }*/ - if err := d.setLinkAddressV4("tunl0", address); err != nil { - log.WithError(err).Warn("Failed to set tunnel device IP") + if err := m.setLinkAddressV4(m.ipipDevice, address); err != nil { + m.logCtx.WithError(err).Warn("Failed to set tunnel device IP") return err } return nil @@ -156,21 +598,21 @@ func (d *ipipManager) configureIPIPDevice(mtu int, address net.IP, xsumBroken bo // setLinkAddressV4 updates the given link to set its local IP address. It removes any other // addresses. -func (d *ipipManager) setLinkAddressV4(linkName string, address net.IP) error { - logCxt := log.WithFields(log.Fields{ +func (m *ipipManager) setLinkAddressV4(linkName string, address net.IP) error { + logCxt := m.logCtx.WithFields(logrus.Fields{ "link": linkName, "addr": address, }) logCxt.Debug("Setting local IPv4 address on link.") - link, err := d.dataplane.LinkByName(linkName) + link, err := m.nlHandle.LinkByName(linkName) if err != nil { - log.WithError(err).WithField("name", linkName).Warning("Failed to get device") + m.logCtx.WithError(err).WithField("name", linkName).Warning("Failed to get device") return err } - addrs, err := d.dataplane.AddrList(link, netlink.FAMILY_V4) + addrs, err := m.nlHandle.AddrList(link, netlink.FAMILY_V4) if err != nil { - log.WithError(err).Warn("Failed to list interface addresses") + m.logCtx.WithError(err).Warn("Failed to list interface addresses") return err } @@ -182,8 +624,8 @@ func (d *ipipManager) setLinkAddressV4(linkName string, address net.IP) error { continue } logCxt.WithField("oldAddr", oldAddr).Info("Removing old address") - if err := d.dataplane.AddrDel(link, &oldAddr); err != nil { - log.WithError(err).Warn("Failed to delete address") + if err := m.nlHandle.AddrDel(link, &oldAddr); err != nil { + m.logCtx.WithError(err).Warn("Failed to delete address") return err } } @@ -198,8 +640,8 @@ func (d *ipipManager) setLinkAddressV4(linkName string, address net.IP) error { addr := &netlink.Addr{ IPNet: &ipNet, } - if err := d.dataplane.AddrAdd(link, addr); err != nil { - log.WithError(err).WithField("addr", address).Warn("Failed to add address") + if err := m.nlHandle.AddrAdd(link, addr); err != nil { + m.logCtx.WithError(err).WithField("addr", address).Warn("Failed to add address") return err } } @@ -207,35 +649,3 @@ func (d *ipipManager) setLinkAddressV4(linkName string, address net.IP) error { return nil } - -func (d *ipipManager) OnUpdate(msg interface{}) { - switch msg := msg.(type) { - case *proto.HostMetadataUpdate: - log.WithField("hostname", msg.Hostname).Debug("Host update/create") - d.activeHostnameToIP[msg.Hostname] = msg.Ipv4Addr - d.ipSetInSync = false - case *proto.HostMetadataRemove: - log.WithField("hostname", msg.Hostname).Debug("Host removed") - delete(d.activeHostnameToIP, msg.Hostname) - d.ipSetInSync = false - } -} - -func (m *ipipManager) CompleteDeferredWork() error { - if !m.ipSetInSync { - // For simplicity (and on the assumption that host add/removes are rare) rewrite - // the whole IP set whenever we get a change. To replace this with delta handling - // would require reference counting the IPs because it's possible for two hosts - // to (at least transiently) share an IP. That would add occupancy and make the - // code more complex. - log.Info("All-hosts IP set out-of sync, refreshing it.") - members := make([]string, 0, len(m.activeHostnameToIP)+len(m.externalNodeCIDRs)) - for _, ip := range m.activeHostnameToIP { - members = append(members, ip) - } - members = append(members, m.externalNodeCIDRs...) - m.ipsetsDataplane.AddOrReplaceIPSet(m.ipSetMetadata, members) - m.ipSetInSync = true - } - return nil -} diff --git a/felix/dataplane/linux/ipip_mgr_netlink.go b/felix/dataplane/linux/ipip_mgr_netlink.go deleted file mode 100644 index 6c7a6a0bc99..00000000000 --- a/felix/dataplane/linux/ipip_mgr_netlink.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2017 Tigera, Inc. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package intdataplane - -import ( - "errors" - "os/exec" - - "github.com/vishvananda/netlink" - "golang.org/x/sys/unix" -) - -// ipipDataplane is a shim interface for mocking netlink and os/exec in the IPIP manager. -type ipipDataplane interface { - LinkByName(name string) (netlink.Link, error) - LinkSetMTU(link netlink.Link, mtu int) error - LinkSetUp(link netlink.Link) error - AddrList(link netlink.Link, family int) ([]netlink.Addr, error) - AddrAdd(link netlink.Link, addr *netlink.Addr) error - AddrDel(link netlink.Link, addr *netlink.Addr) error - RunCmd(name string, args ...string) error -} - -type realIPIPNetlink struct{} - -func (r realIPIPNetlink) LinkByName(name string) (netlink.Link, error) { - return netlink.LinkByName(name) -} -func (r realIPIPNetlink) LinkSetMTU(link netlink.Link, mtu int) error { - return netlink.LinkSetMTU(link, mtu) -} - -func (r realIPIPNetlink) LinkSetUp(link netlink.Link) error { - return netlink.LinkSetUp(link) -} - -func (r realIPIPNetlink) AddrList(link netlink.Link, family int) ([]netlink.Addr, error) { - retries := 3 - for { - addrs, err := netlink.AddrList(link, family) - if errors.Is(err, unix.EINTR) && retries > 0 { - retries-- - continue - } - return addrs, err - } -} - -func (r realIPIPNetlink) AddrAdd(link netlink.Link, addr *netlink.Addr) error { - return netlink.AddrAdd(link, addr) -} - -func (r realIPIPNetlink) AddrDel(link netlink.Link, addr *netlink.Addr) error { - return netlink.AddrDel(link, addr) -} - -func (r realIPIPNetlink) RunCmd(name string, args ...string) error { - cmd := exec.Command(name, args...) - return cmd.Run() -} diff --git a/felix/dataplane/linux/ipip_mgr_test.go b/felix/dataplane/linux/ipip_mgr_test.go index ffef1469712..1b668fecf0f 100644 --- a/felix/dataplane/linux/ipip_mgr_test.go +++ b/felix/dataplane/linux/ipip_mgr_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2017-2024 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,9 +15,11 @@ package intdataplane import ( + "context" "errors" "fmt" "net" + "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -25,7 +27,11 @@ import ( "github.com/vishvananda/netlink" dpsets "github.com/projectcalico/calico/felix/dataplane/ipsets" + "github.com/projectcalico/calico/felix/dataplane/linux/dataplanedefs" + "github.com/projectcalico/calico/felix/logutils" "github.com/projectcalico/calico/felix/proto" + "github.com/projectcalico/calico/felix/routetable" + "github.com/projectcalico/calico/felix/rules" "github.com/projectcalico/calico/libcalico-go/lib/set" ) @@ -39,6 +45,7 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { ipipMgr *ipipManager ipSets *dpsets.MockIPSets dataplane *mockIPIPDataplane + rt *mockRouteTable ) ip, _, err := net.ParseCIDR("10.0.0.1/32") @@ -51,9 +58,25 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { } BeforeEach(func() { - dataplane = &mockIPIPDataplane{} + dataplane = &mockIPIPDataplane{ + tunnelLineName: dataplanedefs.IPIPDefaultIfaceNameV4, + } ipSets = dpsets.NewMockIPSets() - ipipMgr = newIPIPManagerWithShim(ipSets, 1024, dataplane, nil) + rt = &mockRouteTable{ + currentRoutes: map[string][]routetable.Target{}, + } + opRecorder := logutils.NewSummarizer("test") + ipipMgr = newIPIPManagerWithShim( + ipSets, rt, dataplanedefs.IPIPDefaultIfaceNameV4, + Config{ + MaxIPSetSize: 1024, + Hostname: "node1", + ExternalNodesCidrs: nil, + }, + opRecorder, + dataplane, + 4, + ) }) Describe("after calling configureIPIPDevice", func() { @@ -63,6 +86,7 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { } BeforeEach(func() { + ipipMgr.OnParentNameUpdate("eth0") err = ipipMgr.configureIPIPDevice(1400, ip, false) Expect(err).ToNot(HaveOccurred()) }) @@ -88,7 +112,7 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { Expect(err).ToNot(HaveOccurred()) }) It("should avoid creating the interface", func() { - Expect(dataplane.RunCmdCalled).To(BeFalse()) + Expect(dataplane.LinkAddCalled).To(BeFalse()) }) It("should avoid setting the interface UP again", func() { Expect(dataplane.LinkSetUpCalled).To(BeFalse()) @@ -108,7 +132,7 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { Expect(err).ToNot(HaveOccurred()) }) It("should avoid creating the interface", func() { - Expect(dataplane.RunCmdCalled).To(BeFalse()) + Expect(dataplane.LinkAddCalled).To(BeFalse()) }) It("should avoid setting the interface UP again", func() { Expect(dataplane.LinkSetUpCalled).To(BeFalse()) @@ -129,7 +153,7 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { Expect(err).ToNot(HaveOccurred()) }) It("should avoid creating the interface", func() { - Expect(dataplane.RunCmdCalled).To(BeFalse()) + Expect(dataplane.LinkAddCalled).To(BeFalse()) }) It("should avoid setting the interface UP again", func() { Expect(dataplane.LinkSetUpCalled).To(BeFalse()) @@ -203,9 +227,9 @@ var _ = Describe("IpipMgr (tunnel configuration)", func() { var _ = Describe("ipipManager IP set updates", func() { var ( - ipipMgr *ipipManager - ipSets *dpsets.MockIPSets - dataplane *mockIPIPDataplane + ipipMgr *ipipManager + ipSets *dpsets.MockIPSets + rt *mockRouteTable ) const ( @@ -213,9 +237,33 @@ var _ = Describe("ipipManager IP set updates", func() { ) BeforeEach(func() { - dataplane = &mockIPIPDataplane{} ipSets = dpsets.NewMockIPSets() - ipipMgr = newIPIPManagerWithShim(ipSets, 1024, dataplane, []string{externalCIDR}) + rt = &mockRouteTable{ + currentRoutes: map[string][]routetable.Target{}, + } + + la := netlink.NewLinkAttrs() + la.Name = "eth0" + opRecorder := logutils.NewSummarizer("test") + ipipMgr = newIPIPManagerWithShim( + ipSets, rt, dataplanedefs.IPIPDefaultIfaceNameV4, + Config{ + MaxIPSetSize: 1024, + Hostname: "host1", + ExternalNodesCidrs: []string{externalCIDR}, + }, + opRecorder, + &mockIPIPDataplane{ + links: []netlink.Link{&mockLink{attrs: la}}, + tunnelLineName: dataplanedefs.IPIPDefaultIfaceNameV4, + }, + 4, + ) + ipipMgr.OnUpdate(&proto.HostMetadataUpdate{ + Hostname: "host1", + Ipv4Addr: "10.0.0.1", + }) + ipipMgr.OnParentNameUpdate("eth0") }) It("should not create the IP set until first call to CompleteDeferredWork()", func() { @@ -343,22 +391,176 @@ var _ = Describe("ipipManager IP set updates", func() { }) }) +var _ = Describe("IPIPManager", func() { + var manager *ipipManager + var rt *mockRouteTable + var ipSets *dpsets.MockIPSets + + BeforeEach(func() { + ipSets = dpsets.NewMockIPSets() + rt = &mockRouteTable{ + currentRoutes: map[string][]routetable.Target{}, + } + + la := netlink.NewLinkAttrs() + la.Name = "eth0" + opRecorder := logutils.NewSummarizer("test") + manager = newIPIPManagerWithShim( + ipSets, rt, dataplanedefs.IPIPIfaceNameV4, + Config{ + MaxIPSetSize: 1024, + Hostname: "host1", + ExternalNodesCidrs: []string{"10.10.10.0/24"}, + RulesConfig: rules.Config{ + IPIPTunnelAddress: net.ParseIP("192.168.0.1"), + }, + ProgramIPIPRoutes: true, + IPIPMTU: 1400, + }, + opRecorder, + &mockIPIPDataplane{ + links: []netlink.Link{&mockLink{attrs: la}}, + tunnelLineName: dataplanedefs.IPIPIfaceNameV4, + }, + 4, + ) + }) + + It("successfully adds a route to the parent interface", func() { + manager.OnUpdate(&proto.HostMetadataUpdate{ + Hostname: "host1", + Ipv4Addr: "10.0.0.1", + }) + manager.OnUpdate(&proto.HostMetadataUpdate{ + Hostname: "host2", + Ipv4Addr: "10.0.1.1", + }) + + err := manager.configureIPIPDevice(50, manager.dpConfig.RulesConfig.IPIPTunnelAddress, false) + Expect(err).NotTo(HaveOccurred()) + manager.OnParentNameUpdate("eth0") + + Expect(manager.hostAddr).NotTo(BeZero()) + Expect(manager.parentIfaceName).NotTo(BeEmpty()) + parent, err := manager.getParentInterface() + + Expect(parent).NotTo(BeNil()) + Expect(err).NotTo(HaveOccurred()) + + manager.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_REMOTE_WORKLOAD, + IpPoolType: proto.IPPoolType_IPIP, + Dst: "192.168.0.3/26", + DstNodeName: "host2", + DstNodeIp: "10.0.1.1", + SameSubnet: true, + }) + + manager.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_REMOTE_WORKLOAD, + IpPoolType: proto.IPPoolType_IPIP, + Dst: "192.168.0.2/26", + DstNodeName: "host2", + DstNodeIp: "10.0.1.1", + }) + + manager.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_LOCAL_WORKLOAD, + IpPoolType: proto.IPPoolType_IPIP, + Dst: "192.168.0.100/26", + DstNodeName: "host1", + DstNodeIp: "10.0.0.1", + SameSubnet: true, + }) + + // Borrowed /32 should not be programmed as blackhole. + manager.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_LOCAL_WORKLOAD, + IpPoolType: proto.IPPoolType_IPIP, + Dst: "192.168.0.10/32", + DstNodeName: "host1", + DstNodeIp: "10.0.0.7", + SameSubnet: true, + }) + + Expect(rt.currentRoutes[dataplanedefs.IPIPIfaceNameV4]).To(HaveLen(0)) + Expect(rt.currentRoutes[routetable.InterfaceNone]).To(HaveLen(0)) + + err = manager.CompleteDeferredWork() + + Expect(err).NotTo(HaveOccurred()) + Expect(rt.currentRoutes[dataplanedefs.IPIPIfaceNameV4]).To(HaveLen(1)) + Expect(rt.currentRoutes[routetable.InterfaceNone]).To(HaveLen(1)) + Expect(rt.currentRoutes["eth0"]).NotTo(BeNil()) + }) + + It("adds the route to the default table on next try when the parent route table is not immediately found", func() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + parentNameC := make(chan string) + go manager.KeepCalicoIPIPDeviceInSync(ctx, false, 1*time.Second, parentNameC) + + manager.OnUpdate(&proto.HostMetadataUpdate{ + Hostname: "host2", + Ipv4Addr: "10.0.1.1/32", + }) + + manager.OnUpdate(&proto.RouteUpdate{ + Type: proto.RouteType_REMOTE_WORKLOAD, + IpPoolType: proto.IPPoolType_IPIP, + Dst: "172.0.0.1/26", + DstNodeName: "host2", + DstNodeIp: "172.8.8.8", + SameSubnet: true, + }) + + err := manager.CompleteDeferredWork() + Expect(err).NotTo(BeNil()) + Expect(err.Error()).To(Equal("no encap route table not set, will defer adding routes")) + Expect(manager.routesDirty).To(BeTrue()) + + manager.OnUpdate(&proto.HostMetadataUpdate{ + Hostname: "host1", + Ipv4Addr: "10.0.0.1", + }) + + Expect(manager.hostAddr).NotTo(BeZero()) + + // Note: parent name is sent after configuration so this receive + // ensures we don't race. + Eventually(parentNameC, "2s").Should(Receive(Equal("eth0"))) + manager.OnParentNameUpdate("eth0") + + err = manager.configureIPIPDevice(50, manager.dpConfig.RulesConfig.IPIPTunnelAddress, false) + Expect(err).NotTo(HaveOccurred()) + + Expect(rt.currentRoutes["eth0"]).To(HaveLen(0)) + err = manager.CompleteDeferredWork() + Expect(err).NotTo(HaveOccurred()) + Expect(manager.routesDirty).To(BeFalse()) + Expect(rt.currentRoutes["eth0"]).To(HaveLen(1)) + }) +}) + type mockIPIPDataplane struct { tunnelLink *mockLink tunnelLinkAttrs *netlink.LinkAttrs + tunnelLineName string addrs []netlink.Addr - RunCmdCalled bool + LinkAddCalled bool LinkSetMTUCalled bool LinkSetUpCalled bool AddrUpdated bool NumCalls int ErrorAtCall int + + links []netlink.Link } func (d *mockIPIPDataplane) ResetCalls() { - d.RunCmdCalled = false + d.LinkAddCalled = false d.LinkSetMTUCalled = false d.LinkSetUpCalled = false d.AddrUpdated = false @@ -380,7 +582,7 @@ func (d *mockIPIPDataplane) LinkByName(name string) (netlink.Link, error) { return nil, err } - Expect(name).To(Equal("tunl0")) + Expect(name).To(Equal(d.tunnelLineName)) if d.tunnelLink == nil { return nil, notFound } @@ -392,7 +594,7 @@ func (d *mockIPIPDataplane) LinkSetMTU(link netlink.Link, mtu int) error { if err := d.incCallCount(); err != nil { return err } - Expect(link.Attrs().Name).To(Equal("tunl0")) + Expect(link.Attrs().Name).To(Equal(d.tunnelLineName)) d.tunnelLinkAttrs.MTU = mtu return nil } @@ -402,7 +604,7 @@ func (d *mockIPIPDataplane) LinkSetUp(link netlink.Link) error { if err := d.incCallCount(); err != nil { return err } - Expect(link.Attrs().Name).To(Equal("tunl0")) + Expect(link.Attrs().Name).To(Equal(d.tunnelLineName)) d.tunnelLinkAttrs.Flags |= net.FlagUp return nil } @@ -411,7 +613,16 @@ func (d *mockIPIPDataplane) AddrList(link netlink.Link, family int) ([]netlink.A if err := d.incCallCount(); err != nil { return nil, err } - Expect(link.Attrs().Name).To(Equal("tunl0")) + + name := link.Attrs().Name + Expect(name).Should(BeElementOf(d.tunnelLineName, "eth0")) + if name == "eth0" { + return []netlink.Addr{{ + IPNet: &net.IPNet{ + IP: net.IPv4(10, 0, 0, 1), + }}, + }, nil + } return d.addrs, nil } @@ -436,25 +647,30 @@ func (d *mockIPIPDataplane) AddrDel(link netlink.Link, addr *netlink.Addr) error return nil } -func (d *mockIPIPDataplane) RunCmd(name string, args ...string) error { - d.RunCmdCalled = true +func (d *mockIPIPDataplane) LinkList() ([]netlink.Link, error) { + return d.links, nil +} + +func (d *mockIPIPDataplane) LinkAdd(l netlink.Link) error { + d.LinkAddCalled = true if err := d.incCallCount(); err != nil { return err } - log.WithFields(log.Fields{"name": name, "args": args}).Info("RunCmd called") - Expect(name).To(Equal("ip")) - Expect(args).To(Equal([]string{"tunnel", "add", "tunl0", "mode", "ipip"})) - + Expect(l.Attrs().Name).To(Equal(d.tunnelLineName)) if d.tunnelLink == nil { log.Info("Creating tunnel link") link := &mockLink{} - link.attrs.Name = "tunl0" + link.attrs.Name = d.tunnelLineName d.tunnelLinkAttrs = &link.attrs d.tunnelLink = link } return nil } +func (d *mockIPIPDataplane) LinkDel(_ netlink.Link) error { + return nil +} + type mockLink struct { attrs netlink.LinkAttrs typ string diff --git a/felix/dataplane/linux/routing_utility.go b/felix/dataplane/linux/routing_utility.go new file mode 100644 index 00000000000..8cc0d731e21 --- /dev/null +++ b/felix/dataplane/linux/routing_utility.go @@ -0,0 +1,128 @@ +// Copyright (c) 2024 Tigera, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package intdataplane + +import ( + "strings" + "syscall" + + "github.com/sirupsen/logrus" + "github.com/vishvananda/netlink" + + "github.com/projectcalico/calico/felix/dataplane/linux/dataplanedefs" + "github.com/projectcalico/calico/felix/ip" + "github.com/projectcalico/calico/felix/proto" + "github.com/projectcalico/calico/felix/routetable" +) + +// added so that we can shim netlink for tests +type netlinkHandle interface { + LinkByName(name string) (netlink.Link, error) + LinkSetMTU(link netlink.Link, mtu int) error + LinkSetUp(link netlink.Link) error + AddrList(link netlink.Link, family int) ([]netlink.Addr, error) + AddrAdd(link netlink.Link, addr *netlink.Addr) error + AddrDel(link netlink.Link, addr *netlink.Addr) error + LinkList() ([]netlink.Link, error) + LinkAdd(netlink.Link) error + LinkDel(netlink.Link) error +} + +func routeIsLocalBlock(msg *proto.RouteUpdate, routeProto proto.IPPoolType) bool { + // RouteType_LOCAL_WORKLOAD means "local IPAM block _or_ /32 of workload" in IPv4. + // It means "local IPAM block _or_ /128 of workload" in IPv6. + if msg.Type != proto.RouteType_LOCAL_WORKLOAD { + return false + } + // Only care about a specific ippool + if msg.IpPoolType != routeProto { + return false + } + // Ignore routes that we know are from local workload endpoints. + if msg.LocalWorkload { + return false + } + + // Check the valid suffix depending on IP version. + cidr, err := ip.CIDRFromString(msg.Dst) + if err != nil { + logrus.WithError(err).WithField("msg", msg).Warning("Unable to parse destination into a CIDR. Treating block as external.") + } + // Ignore exact routes, i.e. /32 (ipv4) or /128 (ipv6) routes in any case for two reasons: + // * If we have a /32 or /128 block then our blackhole route would stop the CNI plugin from + // programming its /32 or /128 for a newly added workload. + // * If this isn't a /32 or /128 block then it must be a borrowed /32 or /128 from another + // block. In that case, we know we're racing with CNI, adding a new workload. + // We've received the borrowed IP but not the workload endpoint yet. + exactRoute := "/32" + if cidr.Version() == 6 { + exactRoute = "/128" + } + return !strings.HasSuffix(msg.Dst, exactRoute) +} + +func blackholeRoutes(localIPAMBlocks map[string]*proto.RouteUpdate, proto netlink.RouteProtocol) []routetable.Target { + var rtt []routetable.Target + for dst := range localIPAMBlocks { + cidr, err := ip.CIDRFromString(dst) + if err != nil { + logrus.WithError(err).Warning( + "Error processing IPAM block CIDR: ", dst, + ) + continue + } + rtt = append(rtt, routetable.Target{ + Type: routetable.TargetTypeBlackhole, + CIDR: cidr, + Protocol: proto, + }) + } + return rtt +} + +func noEncapRoute(parentIface string, cidr ip.CIDR, r *proto.RouteUpdate, proto netlink.RouteProtocol) *routetable.Target { + if parentIface == "" { + return nil + } + if !r.GetSameSubnet() { + return nil + } + if r.DstNodeIp == "" { + return nil + } + noEncapRoute := routetable.Target{ + Type: routetable.TargetTypeNoEncap, + CIDR: cidr, + GW: ip.FromString(r.DstNodeIp), + Protocol: proto, + } + return &noEncapRoute +} + +func calculateRouteProtocol(dpConfig Config) netlink.RouteProtocol { + // For same-subnet and blackhole routes, we need a unique protocol + // to attach to the routes. If the global DeviceRouteProtocol is set to + // a usable value, use that; otherwise, pick a safer default. (For back + // compatibility, our DeviceRouteProtocol defaults to RTPROT_BOOT, which + // can also be used by other processes.) + // + // Routes to the VXLAN tunnel device itself are identified by their target + // interface. We don't need to worry about their protocol. + noEncapProtocol := dataplanedefs.DefaultRoutingProto + if dpConfig.DeviceRouteProtocol != syscall.RTPROT_BOOT { + noEncapProtocol = dpConfig.DeviceRouteProtocol + } + return noEncapProtocol +} diff --git a/felix/dataplane/linux/vxlan_mgr.go b/felix/dataplane/linux/vxlan_mgr.go index 997b4cfcca9..7a6c420afaf 100644 --- a/felix/dataplane/linux/vxlan_mgr.go +++ b/felix/dataplane/linux/vxlan_mgr.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2024 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,7 +20,6 @@ import ( "fmt" "net" "reflect" - "strings" "sync" "syscall" "time" @@ -29,7 +28,6 @@ import ( "github.com/vishvananda/netlink" dpsets "github.com/projectcalico/calico/felix/dataplane/ipsets" - "github.com/projectcalico/calico/felix/dataplane/linux/dataplanedefs" "github.com/projectcalico/calico/felix/ethtool" "github.com/projectcalico/calico/felix/ip" "github.com/projectcalico/calico/felix/ipsets" @@ -41,19 +39,6 @@ import ( "github.com/projectcalico/calico/felix/vxlanfdb" ) -// added so that we can shim netlink for tests -type netlinkHandle interface { - LinkByName(name string) (netlink.Link, error) - LinkSetMTU(link netlink.Link, mtu int) error - LinkSetUp(link netlink.Link) error - AddrList(link netlink.Link, family int) ([]netlink.Addr, error) - AddrAdd(link netlink.Link, addr *netlink.Addr) error - AddrDel(link netlink.Link, addr *netlink.Addr) error - LinkList() ([]netlink.Link, error) - LinkAdd(netlink.Link) error - LinkDel(netlink.Link) error -} - type vxlanManager struct { // Our dependencies. hostname string @@ -85,7 +70,7 @@ type vxlanManager struct { vtepsDirty bool nlHandle netlinkHandle dpConfig Config - noEncapProtocol netlink.RouteProtocol + routeProtocol netlink.RouteProtocol // Log context logCtx *logrus.Entry @@ -128,7 +113,6 @@ func newVXLANManagerWithShims( nlHandle netlinkHandle, ipVersion uint8, ) *vxlanManager { - logCtx := logrus.WithField("ipVersion", ipVersion) return &vxlanManager{ ipsetsDataplane: ipsetsDataplane, ipSetMetadata: ipsets.IPSetMetadata{ @@ -152,28 +136,12 @@ func newVXLANManagerWithShims( vtepsDirty: true, dpConfig: dpConfig, nlHandle: nlHandle, - noEncapProtocol: calculateNonEncapRouteProtocol(dpConfig), - logCtx: logCtx, + routeProtocol: calculateRouteProtocol(dpConfig), + logCtx: logrus.WithField("ipVersion", ipVersion), opRecorder: opRecorder, } } -func calculateNonEncapRouteProtocol(dpConfig Config) netlink.RouteProtocol { - // For same-subnet and blackhole routes, we need a unique protocol - // to attach to the routes. If the global DeviceRouteProtocol is set to - // a usable value, use that; otherwise, pick a safer default. (For back - // compatibility, our DeviceRouteProtocol defaults to RTPROT_BOOT, which - // can also be used by other processes.) - // - // Routes to the VXLAN tunnel device itself are identified by their target - // interface. We don't need to worry about their protocol. - noEncapProtocol := dataplanedefs.VXLANDefaultProto - if dpConfig.DeviceRouteProtocol != syscall.RTPROT_BOOT { - noEncapProtocol = dpConfig.DeviceRouteProtocol - } - return noEncapProtocol -} - func (m *vxlanManager) OnUpdate(protoBufMsg interface{}) { switch msg := protoBufMsg.(type) { case *proto.RouteUpdate: @@ -207,7 +175,7 @@ func (m *vxlanManager) OnUpdate(protoBufMsg interface{}) { } // Process IPAM blocks that aren't associated to a single or /32 local workload - if routeIsLocalVXLANBlock(msg) { + if routeIsLocalBlock(msg, proto.IPPoolType_VXLAN) { m.logCtx.WithField("msg", msg).Debug("VXLAN data plane received route update for IPAM block") m.localIPAMBlocks[msg.Dst] = msg m.routesDirty = true @@ -257,50 +225,6 @@ func (m *vxlanManager) OnUpdate(protoBufMsg interface{}) { } } -func routeIsLocalVXLANBlock(msg *proto.RouteUpdate) bool { - // RouteType_LOCAL_WORKLOAD means "local IPAM block _or_ /32 of workload" in IPv4. - // It means "local IPAM block _or_ /128 of workload" in IPv6. - if msg.Type != proto.RouteType_LOCAL_WORKLOAD { - return false - } - // Only care about VXLAN blocks. - if msg.IpPoolType != proto.IPPoolType_VXLAN { - return false - } - // Ignore routes that we know are from local workload endpoints. - if msg.LocalWorkload { - return false - } - - // Check the valid suffix depending on IP version. - cidr, err := ip.CIDRFromString(msg.Dst) - if err != nil { - logrus.WithError(err).WithField("msg", msg).Warning("Unable to parse destination into a CIDR. Treating block as external.") - } - if cidr.Version() == 4 { - // This is an IPv4 route. - // Ignore /32 routes in any case for two reasons: - // * If we have a /32 block then our blackhole route would stop the CNI plugin from programming its /32 for a - // newly added workload. - // * If this isn't a /32 block then it must be a borrowed /32 from another block. In that case, we know we're - // racing with CNI, adding a new workload. We've received the borrowed IP but not the workload endpoint yet. - if strings.HasSuffix(msg.Dst, "/32") { - return false - } - } else { - // This is an IPv6 route. - // Ignore /128 routes in any case for two reasons: - // * If we have a /128 block then our blackhole route would stop the CNI plugin from programming its /128 for a - // newly added workload. - // * If this isn't a /128 block then it must be a borrowed /128 from another block. In that case, we know we're - // racing with CNI, adding a new workload. We've received the borrowed IP but not the workload endpoint yet. - if strings.HasSuffix(msg.Dst, "/128") { - return false - } - } - return true -} - func (m *vxlanManager) deleteRoute(dst string) { _, exists := m.routesByDest[dst] if exists { @@ -337,26 +261,6 @@ func (m *vxlanManager) getLocalVTEPParent() (netlink.Link, error) { return m.getParentInterface(m.getLocalVTEP()) } -func (m *vxlanManager) blackholeRoutes() []routetable.Target { - var rtt []routetable.Target - for dst := range m.localIPAMBlocks { - cidr, err := ip.CIDRFromString(dst) - if err != nil { - m.logCtx.WithError(err).Warning( - "Error processing IPAM block CIDR: ", dst, - ) - continue - } - rtt = append(rtt, routetable.Target{ - Type: routetable.TargetTypeBlackhole, - CIDR: cidr, - Protocol: m.noEncapProtocol, - }) - } - m.logCtx.Debug("calculated blackholes ", rtt) - return rtt -} - func (m *vxlanManager) CompleteDeferredWork() error { if m.parentIfaceName == "" { // Background goroutine hasn't sent us the parent interface name yet, @@ -390,12 +294,11 @@ func (m *vxlanManager) CompleteDeferredWork() error { m.updateNeighborsAndAllowedSources() m.vtepsDirty = false } - if m.routesDirty { m.updateRoutes() m.routesDirty = false } - + m.logCtx.Info("VXLAN Manager completed deferred work") return nil } @@ -452,7 +355,7 @@ func (m *vxlanManager) updateRoutes() { continue } - if noEncapRoute := m.noEncapRoute(cidr, r); noEncapRoute != nil { + if noEncapRoute := noEncapRoute(m.parentIfaceName, cidr, r, m.routeProtocol); noEncapRoute != nil { // We've got everything we need to program this route as a no-encap route. noEncapRoutes = append(noEncapRoutes, *noEncapRoute) logCtx.WithField("route", r).Debug("Destination in same subnet, using no-encap route.") @@ -466,7 +369,10 @@ func (m *vxlanManager) updateRoutes() { m.logCtx.WithField("vxlanRoutes", vxlanRoutes).Debug("VXLAN manager setting VXLAN tunneled routes") m.routeTable.SetRoutes(routetable.RouteClassVXLANTunnel, m.vxlanDevice, vxlanRoutes) - m.routeTable.SetRoutes(routetable.RouteClassIPAMBlockDrop, routetable.InterfaceNone, m.blackholeRoutes()) + + bhRoutes := blackholeRoutes(m.localIPAMBlocks, m.routeProtocol) + m.logCtx.WithField("balckholes", bhRoutes).Debug("VXLAN manager setting blackhole routes") + m.routeTable.SetRoutes(routetable.RouteClassIPAMBlockDrop, routetable.InterfaceNone, bhRoutes) if m.parentIfaceName != "" { m.logCtx.WithFields(logrus.Fields{ @@ -479,25 +385,6 @@ func (m *vxlanManager) updateRoutes() { } } -func (m *vxlanManager) noEncapRoute(cidr ip.CIDR, r *proto.RouteUpdate) *routetable.Target { - if !r.GetSameSubnet() { - return nil - } - if m.parentIfaceName == "" { - return nil - } - if r.DstNodeIp == "" { - return nil - } - noEncapRoute := routetable.Target{ - Type: routetable.TargetTypeNoEncap, - CIDR: cidr, - GW: ip.FromString(r.DstNodeIp), - Protocol: m.noEncapProtocol, - } - return &noEncapRoute -} - func (m *vxlanManager) tunneledRoute(cidr ip.CIDR, r *proto.RouteUpdate) *routetable.Target { if r.Type == proto.RouteType_REMOTE_TUNNEL { // We treat remote tunnel routes as directly connected. They don't have a gateway of @@ -516,9 +403,10 @@ func (m *vxlanManager) tunneledRoute(cidr ip.CIDR, r *proto.RouteUpdate) *routet vtepAddr = vtep.Ipv6Addr } return &routetable.Target{ - Type: routetable.TargetTypeVXLAN, - CIDR: cidr, - GW: ip.FromString(vtepAddr), + Type: routetable.TargetTypeVXLAN, + CIDR: cidr, + GW: ip.FromString(vtepAddr), + Protocol: m.routeProtocol, } } diff --git a/felix/docs/config-params.json b/felix/docs/config-params.json index b05f190afe2..6190b371195 100644 --- a/felix/docs/config-params.json +++ b/felix/docs/config-params.json @@ -1785,6 +1785,32 @@ "UserEditable": true, "GoType": "string" }, + { + "Group": "Dataplane: Common", + "GroupWithSortPrefix": "10 Dataplane: Common", + "NameConfigFile": "ProgramRoutes", + "NameEnvVar": "FELIX_ProgramRoutes", + "NameYAML": "programRoutes", + "NameGoAPI": "ProgramRoutes", + "StringSchema": "One of: `IPIP`, `None` (case insensitive)", + "StringSchemaHTML": "One of: IPIP, None (case insensitive)", + "StringDefault": "None", + "ParsedDefault": "None", + "ParsedDefaultJSON": "\"None\"", + "ParsedType": "string", + "YAMLType": "string", + "YAMLSchema": "", + "YAMLEnumValues": null, + "YAMLSchemaHTML": "", + "YAMLDefault": "None", + "Required": false, + "OnParseFailure": "ReplaceWithDefault", + "AllowedConfigSources": "All", + "Description": "Specifies what type of routes Felix should program. .", + "DescriptionHTML": "

Specifies what type of routes Felix should program. .

", + "UserEditable": true, + "GoType": "*v3.ProgramRouteMode" + }, { "Group": "Dataplane: Common", "GroupWithSortPrefix": "10 Dataplane: Common", diff --git a/felix/docs/config-params.md b/felix/docs/config-params.md index 79e80b69006..82cbb52319d 100644 --- a/felix/docs/config-params.md +++ b/felix/docs/config-params.md @@ -962,6 +962,19 @@ like Application layer policy. | `FelixConfiguration` schema | String. | | Default value (YAML) | none | +### `ProgramRoutes` (config file) / `programRoutes` (YAML) + +Specifies what type of routes Felix should program. . + +| Detail | | +| --- | --- | +| Environment variable | `FELIX_ProgramRoutes` | +| Encoding (env var/config file) | One of: IPIP, None (case insensitive) | +| Default value (above encoding) | `None` | +| `FelixConfiguration` field | `programRoutes` (YAML) `ProgramRoutes` (Go API) | +| `FelixConfiguration` schema | `string` | +| Default value (YAML) | `None` | + ### `RemoveExternalRoutes` (config file) / `removeExternalRoutes` (YAML) Controls whether Felix will remove unexpected routes to workload interfaces. Felix will diff --git a/felix/fv/apply_on_forward_test.go b/felix/fv/apply_on_forward_test.go index cb5309669f4..74271842a57 100644 --- a/felix/fv/apply_on_forward_test.go +++ b/felix/fv/apply_on_forward_test.go @@ -54,7 +54,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ apply on forward tests; wit infra = getInfra() options := infrastructure.DefaultTopologyOptions() - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever tc, client = infrastructure.StartNNodeTopology(2, options, infra) // Install a default profile that allows all ingress and egress, in the absence of any Policy. diff --git a/felix/fv/bpf_dual_stack_test.go b/felix/fv/bpf_dual_stack_test.go index 17ca764b932..25796693e89 100644 --- a/felix/fv/bpf_dual_stack_test.go +++ b/felix/fv/bpf_dual_stack_test.go @@ -92,8 +92,8 @@ func describeBPFDualStackTests(ctlbEnabled, ipv6Dataplane bool) bool { opts.EnableIPv6 = true opts.NATOutgoingEnabled = true opts.AutoHEPsEnabled = false - opts.IPIPEnabled = false - opts.IPIPRoutesEnabled = false + opts.IPIPMode = api.IPIPModeNever + opts.SimulateRoutes = false opts.DelayFelixStart = true if ipv6Dataplane { diff --git a/felix/fv/bpf_test.go b/felix/fv/bpf_test.go index 7326cbddc5c..ef09257d2e9 100644 --- a/felix/fv/bpf_test.go +++ b/felix/fv/bpf_test.go @@ -375,14 +375,14 @@ func describeBPFTests(opts ...bpfTestOpt) bool { options.NATOutgoingEnabled = true options.AutoHEPsEnabled = true // override IPIP being enabled by default - options.IPIPEnabled = false - options.IPIPRoutesEnabled = false + options.IPIPMode = api.IPIPModeNever + options.SimulateRoutes = false switch testOpts.tunnel { case "none": // nothing case "ipip": - options.IPIPEnabled = true - options.IPIPRoutesEnabled = true + options.IPIPMode = api.IPIPModeAlways + options.SimulateRoutes = true case "vxlan": options.VXLANMode = api.VXLANModeAlways case "wireguard": @@ -5427,7 +5427,7 @@ func ensureBPFProgramsAttached(felix *infrastructure.Felix, ifacesExtra ...strin func ensureBPFProgramsAttachedOffset(offset int, felix *infrastructure.Felix, ifacesExtra ...string) { expectedIfaces := []string{"eth0"} if felix.ExpectedIPIPTunnelAddr != "" { - expectedIfaces = append(expectedIfaces, "tunl0") + expectedIfaces = append(expectedIfaces, felix.TopologyOptions.IPIPDevice) } if felix.ExpectedVXLANTunnelAddr != "" { expectedIfaces = append(expectedIfaces, "vxlan.calico") diff --git a/felix/fv/donottrack_test.go b/felix/fv/donottrack_test.go index 99fab9b21af..54e0b150a3b 100644 --- a/felix/fv/donottrack_test.go +++ b/felix/fv/donottrack_test.go @@ -63,7 +63,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ do-not-track policy tests; if BPFMode() { options.EnableIPv6 = true options.ExtraEnvVars["FELIX_BPFLogLevel"] = "debug" - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever } tc, client = infrastructure.StartNNodeTopology(2, options, infra) cc = &Checker{} diff --git a/felix/fv/ep_to_host_action_test.go b/felix/fv/ep_to_host_action_test.go index a98759cb3fc..f053124fb7c 100644 --- a/felix/fv/ep_to_host_action_test.go +++ b/felix/fv/ep_to_host_action_test.go @@ -51,7 +51,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ endpoint-to-host-action tes } infra = getInfra() options := infrastructure.DefaultTopologyOptions() - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever options.DelayFelixStart = true options.FelixLogSeverity = "Debug" tc, client = infrastructure.StartNNodeTopology(2, options, infra) diff --git a/felix/fv/flow_logs_goladmane_test.go b/felix/fv/flow_logs_goladmane_test.go index ab687d429ee..d673a9b45a1 100644 --- a/felix/fv/flow_logs_goladmane_test.go +++ b/felix/fv/flow_logs_goladmane_test.go @@ -125,7 +125,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ flow log goldmane tests", [ BeforeEach(func() { infra = getInfra() opts = infrastructure.DefaultTopologyOptions() - opts.IPIPEnabled = false + opts.IPIPMode = api.IPIPModeNever opts.FlowLogSource = infrastructure.FlowLogSourceGoldmane opts.ExtraEnvVars["FELIX_BPFCONNTRACKTIMEOUTS"] = "TCPFinsSeen=30s" @@ -583,10 +583,11 @@ var _ = infrastructure.DatastoreDescribe("ipv6 flow log tests", []apiconfig.Data opts.FlowLogSource = infrastructure.FlowLogSourceGoldmane opts.EnableIPv6 = true - opts.IPIPEnabled = false + //opts.IPIPEnabled = false + opts.IPIPMode = api.IPIPModeNever opts.NATOutgoingEnabled = true opts.AutoHEPsEnabled = false - opts.IPIPRoutesEnabled = false + opts.SimulateRoutes = false opts.ExtraEnvVars["FELIX_FLOWLOGSFLUSHINTERVAL"] = "2" opts.ExtraEnvVars["FELIX_IPV6SUPPORT"] = "true" opts.ExtraEnvVars["FELIX_DefaultEndpointToHostAction"] = "RETURN" diff --git a/felix/fv/hostendpoints_test.go b/felix/fv/hostendpoints_test.go index e9615777305..b296b283e12 100644 --- a/felix/fv/hostendpoints_test.go +++ b/felix/fv/hostendpoints_test.go @@ -62,7 +62,7 @@ func describeHostEndpointTests(getInfra infrastructure.InfraFactory, allInterfac BeforeEach(func() { infra = getInfra() options := infrastructure.DefaultTopologyOptions() - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever options.WithTypha = true tc, client = infrastructure.StartNNodeTopology(2, options, infra) @@ -600,7 +600,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ with IP forwarding disabled infra = getInfra() options := infrastructure.DefaultTopologyOptions() options.DelayFelixStart = true - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever options.WithTypha = true options.ExtraEnvVars["FELIX_IPFORWARDING"] = "Disabled" tc, client = infrastructure.StartNNodeTopology(2, options, infra) diff --git a/felix/fv/infrastructure/topology.go b/felix/fv/infrastructure/topology.go index bae702d901d..fe15e40f3b2 100644 --- a/felix/fv/infrastructure/topology.go +++ b/felix/fv/infrastructure/topology.go @@ -26,9 +26,11 @@ import ( "github.com/onsi/ginkgo" . "github.com/onsi/gomega" api "github.com/projectcalico/api/pkg/apis/projectcalico/v3" + v3 "github.com/projectcalico/api/pkg/apis/projectcalico/v3" log "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/projectcalico/calico/felix/dataplane/linux/dataplanedefs" "github.com/projectcalico/calico/felix/fv/containers" client "github.com/projectcalico/calico/libcalico-go/lib/clientv3" "github.com/projectcalico/calico/libcalico-go/lib/errors" @@ -49,16 +51,19 @@ type TopologyOptions struct { EnableIPv6 bool // Temporary flag to implement and test IPv6 in bpf dataplane. // TODO: Remove it when IPv6 implementation in BPF mode is complete. - BPFEnableIPv6 bool - ExtraEnvVars map[string]string - ExtraVolumes map[string]string - WithTypha bool - WithFelixTyphaTLS bool - TestManagesBPF bool - TyphaLogSeverity string - IPIPEnabled bool - IPIPRoutesEnabled bool + BPFEnableIPv6 bool + ExtraEnvVars map[string]string + ExtraVolumes map[string]string + WithTypha bool + WithFelixTyphaTLS bool + TestManagesBPF bool + TyphaLogSeverity string + //IPIPEnabled bool + //IPIPRoutesEnabled bool + IPIPMode api.IPIPMode + IPIPDevice string VXLANMode api.VXLANMode + SimulateRoutes bool WireguardEnabled bool WireguardEnabledV6 bool InitialFelixConfiguration *api.FelixConfiguration @@ -112,11 +117,14 @@ func DefaultTopologyOptions() TopologyOptions { WithTypha: false, WithFelixTyphaTLS: false, TyphaLogSeverity: "info", - IPIPEnabled: true, - IPIPRoutesEnabled: true, - IPPoolCIDR: DefaultIPPoolCIDR, - IPv6PoolCIDR: DefaultIPv6PoolCIDR, - UseIPPools: true, + //IPIPEnabled: true, + //IPIPRoutesEnabled: true, + IPIPMode: v3.IPIPModeAlways, + IPIPDevice: dataplanedefs.IPIPDefaultIfaceNameV4, + SimulateRoutes: true, + IPPoolCIDR: DefaultIPPoolCIDR, + IPv6PoolCIDR: DefaultIPv6PoolCIDR, + UseIPPools: true, } } @@ -139,16 +147,21 @@ func CreateDefaultIPPoolFromOpts( case 4: ipPool.Name = DefaultIPPoolName ipPool.Spec.CIDR = opts.IPPoolCIDR - // IPIP is only supported on IPv4 - if opts.IPIPEnabled { - ipPool.Spec.IPIPMode = api.IPIPModeAlways + /*if opts.IPIPEnabled { + if opts.IPIPRoutesEnabled { + ipPool.Spec.IPIPMode = api.IPIPModeAlways + } else { + ipPool.Spec.IPIPMode = opts.IPIPMode + } } else { ipPool.Spec.IPIPMode = api.IPIPModeNever - } + }*/ + ipPool.Spec.IPIPMode = opts.IPIPMode case 6: ipPool.Name = DefaultIPv6PoolName ipPool.Spec.CIDR = opts.IPv6PoolCIDR + ipPool.Spec.IPIPMode = api.IPIPModeNever default: log.WithField("ipVersion", ipVersion).Panic("Unknown IP version") } @@ -224,7 +237,7 @@ func StartNNodeTopology( success := false var err error - if opts.EnableIPv6 && opts.IPIPEnabled && os.Getenv("FELIX_FV_ENABLE_BPF") == "true" { + if opts.EnableIPv6 && opts.IPIPMode != api.IPIPModeNever && os.Getenv("FELIX_FV_ENABLE_BPF") == "true" { log.Errorf("IPIP not supported in BPF with ipv6!") return } @@ -244,6 +257,10 @@ func StartNNodeTopology( opts.VXLANMode = api.VXLANModeNever } + if opts.IPIPMode == "" { + opts.IPIPMode = api.IPIPModeNever + } + // Get client. client = infra.GetCalicoClient() mustInitDatastore(client) @@ -360,7 +377,7 @@ func StartNNodeTopology( } setUpBGPNodeIPAndIPIPTunnelIP := n > 1 || opts.NeedNodeIP - if opts.IPIPEnabled { + if opts.IPIPMode != api.IPIPModeNever { infra.SetExpectedIPIPTunnelAddr(felix, IPv4CIDR, i, setUpBGPNodeIPAndIPIPTunnelIP) expectedIPs = append(expectedIPs, felix.ExpectedIPIPTunnelAddr) } @@ -443,27 +460,19 @@ func StartNNodeTopology( defer wg.Done() defer ginkgo.GinkgoRecover() jBlock := fmt.Sprintf("%d.%d.%d.0/24", IPv4CIDR.IP[0], IPv4CIDR.IP[1], j) - if opts.IPIPEnabled && opts.IPIPRoutesEnabled { - // Can get "Nexthop device is not up" error here if tunl0 device is - // not ready yet, which can happen especially if Felix start was - // delayed. - Eventually(func() error { - return iFelix.ExecMayFail("ip", "route", "add", jBlock, "via", jFelix.IP, "dev", "tunl0", "onlink") - }, "10s", "1s").ShouldNot(HaveOccurred()) - } else if opts.VXLANMode == api.VXLANModeNever { - // If VXLAN is enabled, Felix will program these routes itself. - err := iFelix.ExecMayFail("ip", "route", "add", jBlock, "via", jFelix.IP, "dev", "eth0") - Expect(err).ToNot(HaveOccurred()) + log.Infof("Marva simulating routes: %v %v %v", opts.VXLANMode, opts.IPIPMode, opts.SimulateRoutes) + if needToSimulateIPIPRoutes(&opts) { + programIPIPRouts(iFelix, jBlock, jFelix.IP) + } else if needToSimulateNoEncapRoutes(&opts) { + programNoEncapRoutes(iFelix, jBlock, jFelix.IP, false) } if opts.EnableIPv6 { - jBlockV6 := fmt.Sprintf("%x%x:%x%x:%x%x:%x%x:%x%x:0:%d:0/112", IPv6CIDR.IP[0], IPv6CIDR.IP[1], IPv6CIDR.IP[2], IPv6CIDR.IP[3], IPv6CIDR.IP[4], IPv6CIDR.IP[5], IPv6CIDR.IP[6], IPv6CIDR.IP[7], IPv6CIDR.IP[8], IPv6CIDR.IP[9], j) - if opts.VXLANMode == api.VXLANModeNever { - // If VXLAN is enabled, Felix will program these routes itself. - // If IPIP routes are enabled, these routes will conflict with configured ones and a 'RTNETLINK answers: File exists' error would occur. - err := iFelix.ExecMayFail("ip", "-6", "route", "add", jBlockV6, "via", jFelix.IPv6, "dev", "eth0") - Expect(err).ToNot(HaveOccurred()) + if needToSimulateNoEncapRoutes(&opts) { + jBlockV6 := fmt.Sprintf("%x%x:%x%x:%x%x:%x%x:%x%x:0:%d:0/112", + IPv6CIDR.IP[0], IPv6CIDR.IP[1], IPv6CIDR.IP[2], IPv6CIDR.IP[3], IPv6CIDR.IP[4], + IPv6CIDR.IP[5], IPv6CIDR.IP[6], IPv6CIDR.IP[7], IPv6CIDR.IP[8], IPv6CIDR.IP[9], j) + programNoEncapRoutes(iFelix, jBlockV6, jFelix.IPv6, true) } - } }(i, j, iFelix, jFelix) } @@ -474,6 +483,36 @@ func StartNNodeTopology( return } +func needToSimulateIPIPRoutes(opts *TopologyOptions) bool { + return opts.IPIPMode == api.IPIPModeAlways && opts.SimulateRoutes +} + +func needToSimulateNoEncapRoutes(opts *TopologyOptions) bool { + log.Infof("Marva simulating routes: %v %v %v", opts.VXLANMode, opts.IPIPMode, opts.SimulateRoutes) + return opts.VXLANMode == api.VXLANModeNever && opts.IPIPMode == api.IPIPModeNever && opts.SimulateRoutes + //return opts.VXLANMode == api.VXLANModeNever +} + +func programIPIPRouts(felix *Felix, dest, gw string) { + // Can get "Nexthop device is not up" error here if tunl0 device is + // not ready yet, which can happen especially if Felix start was delayed. + Eventually(func() error { + return felix.ExecMayFail("ip", "route", "add", dest, "via", gw, "dev", "tunl0", "onlink", "proto", "100") + }, "10s", "1s").ShouldNot(HaveOccurred()) +} + +func programNoEncapRoutes(felix *Felix, dest, gw string, ipv6 bool) { + // If VXLAN is enabled, Felix will program these routes itself. + // If IPIP routes are enabled, these routes will conflict with configured ones and a 'RTNETLINK answers: File exists' error would occur. + if ipv6 { + err := felix.ExecMayFail("ip", "-6", "route", "add", dest, "via", gw, "dev", "eth0") + Expect(err).ToNot(HaveOccurred()) + } else { + err := felix.ExecMayFail("ip", "route", "add", dest, "via", gw, "dev", "eth0") + Expect(err).ToNot(HaveOccurred()) + } +} + func mustInitDatastore(client client.Interface) { Eventually(func() error { log.Info("Initializing the datastore...") diff --git a/felix/fv/ip6tables_test.go b/felix/fv/ip6tables_test.go index 10183e5c95f..cd4591bf953 100644 --- a/felix/fv/ip6tables_test.go +++ b/felix/fv/ip6tables_test.go @@ -56,7 +56,7 @@ var _ = infrastructure.DatastoreDescribe("IPv6 iptables/nftables tests", []apico options = infrastructure.DefaultTopologyOptions() options.EnableIPv6 = true options.FelixLogSeverity = "Debug" - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever iOpts := []infrastructure.CreateOption{ infrastructure.K8sWithIPv6(), diff --git a/felix/fv/ipip_test.go b/felix/fv/ipip_test.go index c17d36271b5..5dc3d73a761 100644 --- a/felix/fv/ipip_test.go +++ b/felix/fv/ipip_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2020-2024 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ import ( "github.com/vishvananda/netlink" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + dpdefs "github.com/projectcalico/calico/felix/dataplane/linux/dataplanedefs" "github.com/projectcalico/calico/felix/fv/connectivity" "github.com/projectcalico/calico/felix/fv/containers" "github.com/projectcalico/calico/felix/fv/infrastructure" @@ -41,11 +42,13 @@ import ( "github.com/projectcalico/calico/libcalico-go/lib/apiconfig" client "github.com/projectcalico/calico/libcalico-go/lib/clientv3" cerrors "github.com/projectcalico/calico/libcalico-go/lib/errors" + "github.com/projectcalico/calico/libcalico-go/lib/ipam" + "github.com/projectcalico/calico/libcalico-go/lib/net" "github.com/projectcalico/calico/libcalico-go/lib/netlinkutils" "github.com/projectcalico/calico/libcalico-go/lib/options" ) -var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ IPIP topology before adding host IPs to IP sets", []apiconfig.DatastoreType{apiconfig.EtcdV3, apiconfig.Kubernetes}, func(getInfra infrastructure.InfraFactory) { +var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ IPIP topology with BIRD programming routes before adding host IPs to IP sets", []apiconfig.DatastoreType{apiconfig.EtcdV3, apiconfig.Kubernetes}, func(getInfra infrastructure.InfraFactory) { var ( bpfEnabled = os.Getenv("FELIX_FV_ENABLE_BPF") == "true" infra infrastructure.DatastoreInfra @@ -492,6 +495,683 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ IPIP topology before adding }) }) +var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ IPIP topology with Felix programming routes before adding host IPs to IP sets", []apiconfig.DatastoreType{apiconfig.EtcdV3, apiconfig.Kubernetes}, func(getInfra infrastructure.InfraFactory) { + type testConf struct { + IPIPMode api.IPIPMode + RouteSource string + BrokenXSum bool + } + for _, testConfig := range []testConf{ + {api.IPIPModeCrossSubnet, "CalicoIPAM", true}, + {api.IPIPModeCrossSubnet, "WorkloadIPs", false}, + + {api.IPIPModeAlways, "CalicoIPAM", true}, + {api.IPIPModeAlways, "WorkloadIPs", false}, + } { + ipipMode := testConfig.IPIPMode + routeSource := testConfig.RouteSource + brokenXSum := testConfig.BrokenXSum + + Describe(fmt.Sprintf("IPIP mode set to %s, routeSource %s, brokenXSum: %v", ipipMode, routeSource, brokenXSum), func() { + var ( + infra infrastructure.DatastoreInfra + tc infrastructure.TopologyContainers + felixes []*infrastructure.Felix + client client.Interface + w [3]*workload.Workload + hostW [3]*workload.Workload + cc *connectivity.Checker + topologyOptions infrastructure.TopologyOptions + ) + + BeforeEach(func() { + infra = getInfra() + if (NFTMode() || BPFMode()) && getDataStoreType(infra) == "etcdv3" { + Skip("Skipping NFT / BPF test for etcdv3 backend.") + } + + topologyOptions = createIPIPBaseTopologyOptions(ipipMode, routeSource, brokenXSum) + tc, client = infrastructure.StartNNodeTopology(3, topologyOptions, infra) + + w, hostW = setupIPIPWorkloads(infra, tc, topologyOptions, client) + felixes = tc.Felixes + + cc = &connectivity.Checker{} + }) + + AfterEach(func() { + if CurrentGinkgoTestDescription().Failed { + for _, felix := range tc.Felixes { + if NFTMode() { + logNFTDiags(felix) + } else { + felix.Exec("iptables-save", "-c") + felix.Exec("ipset", "list") + } + felix.Exec("ip", "r") + felix.Exec("ip", "a") + if BPFMode() { + felix.Exec("calico-bpf", "policy", "dump", "eth0", "all", "--asm") + } + } + } + + for _, wl := range w { + wl.Stop() + } + for _, wl := range hostW { + wl.Stop() + } + tc.Stop() + + if CurrentGinkgoTestDescription().Failed { + infra.DumpErrorData() + } + infra.Stop() + }) + + if brokenXSum { + It("should disable checksum offload", func() { + Eventually(func() string { + out, err := felixes[0].ExecOutput("ethtool", "-k", dpdefs.IPIPIfaceNameV4) + if err != nil { + return fmt.Sprintf("ERROR: %v", err) + } + return out + }, "10s", "100ms").Should(ContainSubstring("tx-checksumming: off")) + }) + } else { + It("should not disable checksum offload", func() { + Eventually(func() string { + out, err := felixes[0].ExecOutput("ethtool", "-k", dpdefs.IPIPIfaceNameV4) + if err != nil { + return fmt.Sprintf("ERROR: %v", err) + } + return out + }, "10s", "100ms").Should(ContainSubstring("tx-checksumming: on")) + }) + } + + It("should fully randomize MASQUERADE rules", func() { + for _, felix := range tc.Felixes { + if NFTMode() { + Eventually(func() string { + out, _ := felix.ExecOutput("nft", "list", "table", "calico") + return out + }, "10s", "100ms").Should(ContainSubstring("fully-random")) + } else { + Eventually(func() string { + out, _ := felix.ExecOutput("iptables-save", "-c") + return out + }, "10s", "100ms").Should(ContainSubstring("--random-fully")) + } + } + }) + + It("should have workload to workload connectivity", func() { + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.CheckConnectivity() + }) + + It("should have some blackhole routes installed", func() { + if routeSource == "WorkloadIPs" { + Skip("not applicable for workload ips") + return + } + + nodes := []string{ + "blackhole 10.65.0.0/26 proto 80", + "blackhole 10.65.1.0/26 proto 80", + "blackhole 10.65.2.0/26 proto 80", + } + + for n, result := range nodes { + Eventually(func() string { + o, _ := felixes[n].ExecOutput("ip", "r", "s", "type", "blackhole") + return o + }, "10s", "100ms").Should(ContainSubstring(result)) + wName := fmt.Sprintf("w%d", n) + + err := client.IPAM().ReleaseByHandle(context.TODO(), wName) + Expect(err).NotTo(HaveOccurred()) + + affinityCfg := ipam.AffinityConfig{ + AffinityType: ipam.AffinityTypeHost, + Host: felixes[n].Hostname, + } + err = client.IPAM().ReleaseHostAffinities(context.TODO(), affinityCfg, true) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() string { + o, _ := felixes[n].ExecOutput("ip", "r", "s", "type", "blackhole") + return o + }, "10s", "100ms").Should(BeEmpty()) + } + }) + + if ipipMode == api.IPIPModeCrossSubnet && routeSource == "CalicoIPAM" { + It("should move same-subnet routes when the node IP moves to a new interface", func() { + // Routes should look like this: + // + // default via 172.17.0.1 dev eth0 + // blackhole 10.65.0.0/26 proto 80 + // 10.65.0.2 dev cali29f56ea1abf scope link + // 10.65.1.0/26 via 172.17.0.6 dev eth0 proto 80 onlink + // 10.65.2.0/26 via 172.17.0.5 dev eth0 proto 80 onlink + // 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.7 + felix := tc.Felixes[0] + Eventually(felix.ExecOutputFn("ip", "route", "show"), "10s").Should(ContainSubstring( + fmt.Sprintf("10.65.1.0/26 via %s dev eth0 proto 80 onlink", tc.Felixes[1].IP))) + + // Find the default and subnet routes, we'll need to + // recreate those after moving the IP. + defaultRoute, err := felix.ExecOutput("ip", "route", "show", "default") + Expect(err).NotTo(HaveOccurred()) + lines := strings.Split(strings.Trim(defaultRoute, "\n "), "\n") + Expect(lines).To(HaveLen(1)) + defaultRouteArgs := strings.Split(strings.Replace(lines[0], "eth0", "bond0", -1), " ") + + // Assuming the subnet route will be "proto kernel" and that will be the only such route. + subnetRoute, err := felix.ExecOutput("ip", "route", "show", "proto", "kernel") + Expect(err).NotTo(HaveOccurred()) + lines = strings.Split(strings.Trim(subnetRoute, "\n "), "\n") + Expect(lines).To(HaveLen(1), "expected only one proto kernel route, has docker's routing set-up changed?") + subnetArgs := strings.Split(strings.Replace(lines[0], "eth0", "bond0", -1), " ") + + // Add the bond, replacing eth0. + felix.Exec("ip", "addr", "del", felix.IP, "dev", "eth0") + felix.Exec("ip", "link", "add", "dev", "bond0", "type", "bond") + felix.Exec("ip", "link", "set", "dev", "eth0", "down") + felix.Exec("ip", "link", "set", "dev", "eth0", "master", "bond0") + felix.Exec("ip", "link", "set", "dev", "eth0", "up") + felix.Exec("ip", "link", "set", "dev", "bond0", "up") + + // Move IP to bond0. We don't actually set up more than one + // bonded interface in this test, we just want to know that + // felix spots the IP move. + ipWithSubnet := felix.IP + "/" + felix.GetIPPrefix() + felix.Exec("ip", "addr", "add", ipWithSubnet, "dev", "bond0") + + // Re-add the default routes, via bond0 (one gets removed when + // eth0 goes down, the other gets stuck on eth0). + felix.Exec(append([]string{"ip", "r", "add"}, defaultRouteArgs...)...) + felix.Exec(append([]string{"ip", "r", "replace"}, subnetArgs...)...) + + expCrossSubRoute := fmt.Sprintf("10.65.1.0/26 via %s dev bond0 proto 80 onlink", tc.Felixes[1].IP) + Eventually(felix.ExecOutputFn("ip", "route", "show"), "60s").Should( + ContainSubstring(expCrossSubRoute), + "Cross-subnet route should move from eth0 to bond0.", + ) + }) + } + + It("should have host to workload connectivity", func() { + if ipipMode == api.IPIPModeAlways && routeSource == "WorkloadIPs" { + Skip("Skipping due to known issue with tunnel IPs not being programmed in WEP mode") + } + cc.ExpectSome(tc.Felixes[0], w[1]) + cc.ExpectSome(tc.Felixes[0], w[0]) + cc.CheckConnectivity() + }) + + It("should have host to host connectivity", func() { + cc.ExpectSome(tc.Felixes[0], hostW[1]) + cc.ExpectSome(tc.Felixes[1], hostW[0]) + cc.CheckConnectivity() + }) + + Context("with host protection policy in place", func() { + BeforeEach(func() { + // Make sure our new host endpoints don't cut felix off from the datastore. + err := infra.AddAllowToDatastore("host-endpoint=='true'") + Expect(err).NotTo(HaveOccurred()) + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + for _, f := range tc.Felixes { + hep := api.NewHostEndpoint() + hep.Name = "eth0-" + f.Name + hep.Labels = map[string]string{ + "host-endpoint": "true", + } + hep.Spec.Node = f.Hostname + hep.Spec.ExpectedIPs = []string{f.IP} + _, err := client.HostEndpoints().Create(ctx, hep, options.SetOptions{}) + Expect(err).NotTo(HaveOccurred()) + } + }) + + It("should have workload connectivity but not host connectivity", func() { + // Host endpoints (with no policies) block host-host traffic due to default drop. + cc.ExpectNone(tc.Felixes[0], hostW[1]) + cc.ExpectNone(tc.Felixes[1], hostW[0]) + // But the rules to allow IPIP between our hosts let the workload traffic through. + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.CheckConnectivity() + }) + }) + + Context("with all-interfaces host protection policy in place", func() { + BeforeEach(func() { + // Make sure our new host endpoints don't cut felix off from the datastore. + err := infra.AddAllowToDatastore("host-endpoint=='true'") + Expect(err).NotTo(HaveOccurred()) + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + // Create host endpoints for each node. + for _, f := range tc.Felixes { + hep := api.NewHostEndpoint() + hep.Name = "all-interfaces-" + f.Name + hep.Labels = map[string]string{ + "host-endpoint": "true", + "hostname": f.Hostname, + } + hep.Spec.Node = f.Hostname + hep.Spec.ExpectedIPs = []string{f.IP} + hep.Spec.InterfaceName = "*" + _, err := client.HostEndpoints().Create(ctx, hep, options.SetOptions{}) + Expect(err).NotTo(HaveOccurred()) + } + }) + + It("should block host-to-host traffic in the absence of policy allowing it", func() { + cc.ExpectNone(tc.Felixes[0], hostW[1]) + cc.ExpectNone(tc.Felixes[1], hostW[0]) + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.CheckConnectivity() + }) + + It("should allow host-to-own-pod traffic in the absence of policy allowing it but not host to other-pods", func() { + cc.ExpectSome(tc.Felixes[0], w[0]) + cc.ExpectSome(tc.Felixes[1], w[1]) + cc.ExpectNone(tc.Felixes[0], w[1]) + cc.ExpectNone(tc.Felixes[1], w[0]) + cc.CheckConnectivity() + }) + + It("should allow felixes[0] to reach felixes[1] if ingress and egress policies are in place", func() { + // Create a policy selecting felix[1] that allows egress. + policy := api.NewGlobalNetworkPolicy() + policy.Name = "f0-egress" + policy.Spec.Egress = []api.Rule{{Action: api.Allow}} + policy.Spec.Selector = fmt.Sprintf("hostname == '%s'", tc.Felixes[0].Hostname) + _, err := client.GlobalNetworkPolicies().Create(utils.Ctx, policy, utils.NoOptions) + Expect(err).NotTo(HaveOccurred()) + + // But there is no policy allowing ingress into felix[1]. + cc.ExpectNone(tc.Felixes[0], hostW[1]) + cc.ExpectNone(tc.Felixes[1], hostW[0]) + + // Workload connectivity is unchanged. + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.CheckConnectivity() + cc.ResetExpectations() + + // Now add a policy selecting felix[1] that allows ingress. + policy = api.NewGlobalNetworkPolicy() + policy.Name = "f1-ingress" + policy.Spec.Ingress = []api.Rule{{Action: api.Allow}} + policy.Spec.Selector = fmt.Sprintf("hostname == '%s'", tc.Felixes[1].Hostname) + _, err = client.GlobalNetworkPolicies().Create(utils.Ctx, policy, utils.NoOptions) + Expect(err).NotTo(HaveOccurred()) + + // Now testContainers.Felix[0] can reach testContainers.Felix[1]. + cc.ExpectSome(tc.Felixes[0], hostW[1]) + cc.ExpectNone(tc.Felixes[1], hostW[0]) + + // Workload connectivity is unchanged. + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.CheckConnectivity() + }) + + Context("with policy allowing port 8055", func() { + BeforeEach(func() { + tcp := numorstring.ProtocolFromString("tcp") + udp := numorstring.ProtocolFromString("udp") + p8055 := numorstring.SinglePort(8055) + policy := api.NewGlobalNetworkPolicy() + policy.Name = "allow-8055" + policy.Spec.Ingress = []api.Rule{ + { + Protocol: &udp, + Destination: api.EntityRule{ + Ports: []numorstring.Port{p8055}, + }, + Action: api.Allow, + }, + { + Protocol: &tcp, + Destination: api.EntityRule{ + Ports: []numorstring.Port{p8055}, + }, + Action: api.Allow, + }, + } + policy.Spec.Egress = []api.Rule{ + { + Protocol: &udp, + Destination: api.EntityRule{ + Ports: []numorstring.Port{p8055}, + }, + Action: api.Allow, + }, + { + Protocol: &tcp, + Destination: api.EntityRule{ + Ports: []numorstring.Port{p8055}, + }, + Action: api.Allow, + }, + } + policy.Spec.Selector = fmt.Sprintf("has(host-endpoint)") + _, err := client.GlobalNetworkPolicies().Create(utils.Ctx, policy, utils.NoOptions) + Expect(err).NotTo(HaveOccurred()) + }) + + // Please take care if adding other connectivity checks into this case, to + // avoid those other checks setting up conntrack state that allows the + // existing case to pass for a different reason. + It("allows host0 to remote Calico-networked workload via service IP", func() { + if ipipMode == api.IPIPModeAlways && routeSource == "WorkloadIPs" { + Skip("Skipping due to known issue with tunnel IPs not being programmed in WEP mode") + } + // Allocate a service IP. + serviceIP := "10.101.0.11" + port := 8055 + tgtPort := 8055 + + createK8sServiceWithoutKubeProxy(createK8sServiceWithoutKubeProxyArgs{ + infra: infra, + felix: tc.Felixes[0], + w: w[1], + svcName: "test-svc", + serviceIP: serviceIP, + targetIP: w[1].IP, + port: port, + tgtPort: tgtPort, + chain: "OUTPUT", + }) + // Expect to connect to the service IP. + cc.ExpectSome(felixes[0], connectivity.TargetIP(serviceIP), uint16(port)) + cc.CheckConnectivity() + }) + }) + }) + + Context("after removing BGP address from third node", func() { + // Simulate having a host send VXLAN traffic from an unknown source, should get blocked. + BeforeEach(func() { + for _, f := range felixes { + if BPFMode() { + Eventually(func() int { + return strings.Count(f.BPFRoutes(), "host") + }).Should(Equal(len(felixes)*2), + "Expected one host and one host tunneled route per node") + } else if NFTMode() { + Eventually(f.NFTSetSizeFn("cali40all-hosts-net"), "10s", "200ms").Should(Equal(len(felixes))) + } else { + Eventually(f.IPSetSizeFn("cali40all-hosts-net"), "10s", "200ms").Should(Equal(len(felixes))) + } + } + + // Pause felix[2], so it can't touch the dataplane; we want to + // test that felix[0] blocks the traffic. + pid := felixes[2].GetFelixPID() + felixes[2].Exec("kill", "-STOP", fmt.Sprint(pid)) + + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + infra.RemoveNodeAddresses(felixes[2]) + node, err := client.Nodes().Get(ctx, felixes[2].Hostname, options.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + node.Spec.BGP = nil + _, err = client.Nodes().Update(ctx, node, options.SetOptions{}) + }) + + It("should have no connectivity from third felix and expected number of IPs in allow list", func() { + if BPFMode() { + Eventually(func() int { + return strings.Count(felixes[0].BPFRoutes(), "host") + }).Should(Equal((len(felixes)-1)*2), + "Expected one host and one host tunneled route per node, not: "+felixes[0].BPFRoutes()) + } else if NFTMode() { + Eventually(felixes[0].NFTSetSizeFn("cali40all-hosts-net"), "5s", "200ms").Should(Equal(len(felixes) - 1)) + } else { + Eventually(felixes[0].IPSetSizeFn("cali40all-hosts-net"), "5s", "200ms").Should(Equal(len(felixes) - 1)) + } + + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.ExpectNone(w[0], w[2]) + cc.ExpectNone(w[1], w[2]) + cc.ExpectNone(w[2], w[0]) + cc.ExpectNone(w[2], w[1]) + cc.CheckConnectivity() + }) + }) + + // Explicitly verify that the IPIP allow-list IP set is doing its job (since Felix makes multiple dataplane + // changes when the BGP IP disappears, and we want to make sure that it's the rule that's causing the + // connectivity to drop). + Context("after removing BGP address from third node, all felixes paused", func() { + // Simulate having a host send IPIP traffic from an unknown source, should get blocked. + BeforeEach(func() { + if BPFMode() { + Skip("Skipping due to manual removal of host from ipset not breaking connectivity in BPF mode") + return + } + + // Check we initially have the expected number of entries. + for _, f := range felixes { + // Wait for Felix to set up the allow list. + if NFTMode() { + Eventually(f.NFTSetSizeFn("cali40all-hosts-net"), "5s", "200ms").Should(Equal(len(felixes))) + } else { + Eventually(f.IPSetSizeFn("cali40all-hosts-net"), "5s", "200ms").Should(Equal(len(felixes))) + } + } + + // Wait until dataplane has settled. + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[0], w[2]) + cc.ExpectSome(w[1], w[2]) + cc.CheckConnectivity() + cc.ResetExpectations() + + // Then pause all the felixes. + for _, f := range felixes { + pid := f.GetFelixPID() + f.Exec("kill", "-STOP", fmt.Sprint(pid)) + } + }) + + // BPF mode doesn't use the IP set. + if ipipMode == api.IPIPModeAlways && !BPFMode() { + It("after manually removing third node from allow list should have expected connectivity", func() { + if NFTMode() { + felixes[0].Exec("nft", "delete", "element", "ip", "calico", "cali40all-hosts-net", fmt.Sprintf("{ %s }", felixes[2].IP)) + } else { + felixes[0].Exec("ipset", "del", "cali40all-hosts-net", felixes[2].IP) + } + + cc.ExpectSome(w[0], w[1]) + cc.ExpectSome(w[1], w[0]) + cc.ExpectSome(w[1], w[2]) + cc.ExpectNone(w[2], w[0]) + cc.CheckConnectivity() + }) + } + }) + + It("should configure the ipip device correctly", func() { + // The ipip device should appear with default MTU, etc. FV environment uses MTU 1500, + // which means that we should expect 1480 after subtracting IPIP overhead for IPv4. + mtuStr := "mtu 1480" + for _, felix := range felixes { + Eventually(func() string { + out, _ := felix.ExecOutput("ip", "-d", "link", "show", dpdefs.IPIPIfaceNameV4) + return out + }, "60s", "500ms").Should(ContainSubstring(mtuStr)) + } + + // Change the host device's MTU, and expect the IPIP device to be updated. + for _, felix := range felixes { + Eventually(func() error { + _, err := felix.ExecOutput("ip", "link", "set", "eth0", "mtu", "1400") + return err + }, "10s", "100ms").Should(BeNil()) + } + + // MTU should be auto-detected, and updated to the host MTU minus 20 bytes overhead IPIP. + mtuStr = "mtu 1380" + mtuValue := "1380" + for _, felix := range felixes { + // Felix checks host MTU every 30s + Eventually(func() string { + out, _ := felix.ExecOutput("ip", "-d", "link", "show", dpdefs.IPIPIfaceNameV4) + return out + }, "60s", "500ms").Should(ContainSubstring(mtuStr)) + + // And expect the MTU file on disk to be updated. + Eventually(func() string { + out, _ := felix.ExecOutput("cat", "/var/lib/calico/mtu") + return out + }, "30s", "100ms").Should(ContainSubstring(mtuValue)) + } + + // Explicitly configure the MTU. + felixConfig := api.NewFelixConfiguration() // Create a default FelixConfiguration + felixConfig.Name = "default" + mtu := 1300 + felixConfig.Spec.IPIPMTU = &mtu + _, err := client.FelixConfigurations().Create(context.Background(), felixConfig, options.SetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + // Expect the settings to be changed on the device. + for _, felix := range felixes { + // Felix checks host MTU every 30s + Eventually(func() string { + out, _ := felix.ExecOutput("ip", "-d", "link", "show", dpdefs.IPIPIfaceNameV4) + return out + }, "60s", "500ms").Should(ContainSubstring("mtu 1300")) + } + }) + + Context("external nodes configured", func() { + var externalClient *containers.Container + + BeforeEach(func() { + externalClient = infrastructure.RunExtClient("ext-client") + + Eventually(func() error { + err := externalClient.ExecMayFail("ip", "tunnel", "add", "tunl0", "mode", "ipip") + if err != nil && strings.Contains(err.Error(), "SIOCADDTUNNEL: File exists") { + return nil + } + return err + }).Should(Succeed()) + + externalClient.Exec("ip", "link", "set", "tunl0", "up") + externalClient.Exec("ip", "addr", "add", "dev", "tunl0", "10.65.222.1") + externalClient.Exec("ip", "route", "add", "10.65.0.0/24", "via", + tc.Felixes[0].IP, "dev", "tunl0", "onlink") + }) + + JustAfterEach(func() { + if CurrentGinkgoTestDescription().Failed { + externalClient.Exec("ip", "r") + externalClient.Exec("ip", "l") + externalClient.Exec("ip", "a") + } + }) + + AfterEach(func() { + externalClient.Stop() + }) + + It("should allow IPIP to external client if it is in ExternalNodesCIDRList", func() { + By("testing that ext client ipip does not work if not part of ExternalNodesCIDRList") + + for _, f := range tc.Felixes { + // Make sure that only the internal nodes are present in the ipset + if BPFMode() { + Eventually(f.BPFRoutes, "10s").Should(ContainSubstring(f.IP)) + Consistently(f.BPFRoutes).ShouldNot(ContainSubstring(externalClient.IP)) + } else if NFTMode() { + Eventually(f.NFTSetSizeFn("cali40all-hosts-net"), "5s", "200ms").Should(Equal(3)) + } else { + Eventually(f.IPSetSizeFn("cali40all-hosts-net"), "5s", "200ms").Should(Equal(3)) + } + } + + cc.ExpectNone(externalClient, w[0]) + cc.CheckConnectivity() + + By("changing configuration to include the external client") + + updateConfig := func(addr string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + c, err := client.FelixConfigurations().Get(ctx, "default", options.GetOptions{}) + if err != nil { + // Create the default config if it doesn't already exist. + if _, ok := err.(cerrors.ErrorResourceDoesNotExist); ok { + c = api.NewFelixConfiguration() + c.Name = "default" + c, err = client.FelixConfigurations().Create(ctx, c, options.SetOptions{}) + Expect(err).NotTo(HaveOccurred()) + } else { + Expect(err).NotTo(HaveOccurred()) + } + } + c.Spec.ExternalNodesCIDRList = &[]string{addr} + log.WithFields(log.Fields{"felixconfiguration": c, "adding Addr": addr}).Info("Updating FelixConfiguration ") + _, err = client.FelixConfigurations().Update(ctx, c, options.SetOptions{}) + Expect(err).NotTo(HaveOccurred()) + } + + updateConfig(externalClient.IP) + + // Wait for the config to take + for _, f := range tc.Felixes { + if BPFMode() { + Eventually(f.BPFRoutes, "10s").Should(ContainSubstring(externalClient.IP)) + Expect(f.IPSetSize("cali40all-hosts-net")).To(BeZero(), + "BPF mode shouldn't program IP sets") + } else if NFTMode() { + Eventually(f.NFTSetSizeFn("cali40all-hosts-net"), "15s", "200ms").Should(Equal(4)) + } else { + Eventually(f.IPSetSizeFn("cali40all-hosts-net"), "15s", "200ms").Should(Equal(4)) + } + } + + // Pause felix[0], so it can't touch the dataplane; we want to + // test that felix[0] blocks the traffic. + pid := felixes[0].GetFelixPID() + felixes[0].Exec("kill", "-STOP", fmt.Sprint(pid)) + + tc.Felixes[0].Exec("ip", "route", "add", "10.65.222.1", "via", + externalClient.IP, "dev", dpdefs.IPIPIfaceNameV4, "onlink", "proto", "90") + + By("testing that the ext client can connect via ipip") + cc.ResetExpectations() + cc.ExpectSome(externalClient, w[0]) + cc.CheckConnectivity() + }) + }) + }) + } +}) + type createK8sServiceWithoutKubeProxyArgs struct { infra infrastructure.DatastoreInfra felix *infrastructure.Felix @@ -533,3 +1213,72 @@ func getDataStoreType(infra infrastructure.DatastoreInfra) string { return "kubernetes" } } + +func createIPIPBaseTopologyOptions( + ipipMode api.IPIPMode, + routeSource string, + brokenXSum bool, +) infrastructure.TopologyOptions { + topologyOptions := infrastructure.DefaultTopologyOptions() + //topologyOptions.IPIPEnabled = true + topologyOptions.IPIPMode = ipipMode + topologyOptions.VXLANMode = api.VXLANModeNever + topologyOptions.IPIPDevice = dpdefs.IPIPIfaceNameV4 + topologyOptions.SimulateRoutes = false + topologyOptions.ExtraEnvVars["FELIX_ProgramRoutes"] = "IPIP" + topologyOptions.ExtraEnvVars["FELIX_ROUTESOURCE"] = routeSource + // We force the broken checksum handling on or off so that we're not dependent on kernel version + // for these tests. Since we're testing in containers anyway, checksum offload can't really be + // tested but we can verify the state with ethtool. + topologyOptions.ExtraEnvVars["FELIX_FeatureDetectOverride"] = fmt.Sprintf("ChecksumOffloadBroken=%t", brokenXSum) + topologyOptions.FelixDebugFilenameRegex = "ipip|route_table|l3_route_resolver|int_dataplane" + return topologyOptions +} + +func setupIPIPWorkloads(infra infrastructure.DatastoreInfra, tc infrastructure.TopologyContainers, to infrastructure.TopologyOptions, client client.Interface) (w, hostW [3]*workload.Workload) { + // Install a default profile that allows all ingress and egress, in the absence of any Policy. + infra.AddDefaultAllow() + + // Wait until the ipip device appears; it is created when felix inserts the ipip module + // into the kernel. + Eventually(func() error { + links, err := netlink.LinkList() + if err != nil { + return err + } + for _, link := range links { + if link.Attrs().Name == "tunl0" { + return nil + } + } + return errors.New("tunl0 wasn't auto-created") + }).Should(BeNil()) + + // Create workloads, using that profile. One on each "host". + _, IPv4CIDR, err := net.ParseCIDR(to.IPPoolCIDR) + Expect(err).To(BeNil()) + for ii := range w { + wIP := fmt.Sprintf("%d.%d.%d.2", IPv4CIDR.IP[0], IPv4CIDR.IP[1], ii) + wName := fmt.Sprintf("w%d", ii) + err := client.IPAM().AssignIP(context.Background(), ipam.AssignIPArgs{ + IP: net.MustParseIP(wIP), + HandleID: &wName, + Attrs: map[string]string{ + ipam.AttributeNode: tc.Felixes[ii].Hostname, + }, + Hostname: tc.Felixes[ii].Hostname, + }) + Expect(err).NotTo(HaveOccurred()) + + w[ii] = workload.Run(tc.Felixes[ii], wName, "default", wIP, "8055", "tcp") + w[ii].ConfigureInInfra(infra) + + hostW[ii] = workload.Run(tc.Felixes[ii], fmt.Sprintf("host%d", ii), "", tc.Felixes[ii].IP, "8055", "tcp") + } + + if BPFMode() { + ensureAllNodesBPFProgramsAttached(tc.Felixes) + } + + return +} diff --git a/felix/fv/latency_test.go b/felix/fv/latency_test.go index 103c58fcf29..58cc7f1a3f3 100644 --- a/felix/fv/latency_test.go +++ b/felix/fv/latency_test.go @@ -62,7 +62,7 @@ var _ = Context("_BPF-SAFE_ Latency tests with initialized Felix and etcd datast BeforeEach(func() { topologyOptions := infrastructure.DefaultTopologyOptions() - topologyOptions.IPIPEnabled = false + topologyOptions.IPIPMode = api.IPIPModeNever topologyOptions.ExtraEnvVars["FELIX_BPFLOGLEVEL"] = "off" // For best perf. tc, etcd, client, infra = infrastructure.StartSingleNodeEtcdTopology(topologyOptions) diff --git a/felix/fv/mtu_test.go b/felix/fv/mtu_test.go index 24903d2b039..68bf2ea16d0 100644 --- a/felix/fv/mtu_test.go +++ b/felix/fv/mtu_test.go @@ -88,7 +88,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ VXLAN topology before addin topologyOptions := infrastructure.DefaultTopologyOptions() topologyOptions.DelayFelixStart = true topologyOptions.VXLANMode = api.VXLANModeAlways - topologyOptions.IPIPEnabled = false + topologyOptions.IPIPMode = api.IPIPModeNever topologyOptions.EnableIPv6 = enableIPv6 // Need n>1 or the infra won't set up IP pools! @@ -137,7 +137,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ VXLAN topology before addin infra = getInfra() topologyOptions := infrastructure.DefaultTopologyOptions() topologyOptions.VXLANMode = api.VXLANModeAlways - topologyOptions.IPIPEnabled = false + topologyOptions.IPIPMode = api.IPIPModeNever topologyOptions.EnableIPv6 = enableIPv6 // Configure the interface pattern so that it doesn't match any host interfaces. diff --git a/felix/fv/routes_test.go b/felix/fv/routes_test.go index d06af021032..5a174f73067 100644 --- a/felix/fv/routes_test.go +++ b/felix/fv/routes_test.go @@ -53,7 +53,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ routing table tests", []api topologyOptions := infrastructure.DefaultTopologyOptions() topologyOptions.VXLANMode = api.VXLANModeAlways - topologyOptions.IPIPEnabled = false + topologyOptions.IPIPMode = api.IPIPModeNever topologyOptions.EnableIPv6 = false topologyOptions.ExtraEnvVars["FELIX_ROUTESOURCE"] = "WorkloadIPs" topologyOptions.FelixDebugFilenameRegex = "route_table.go|vxlan_fdb" diff --git a/felix/fv/service_loop_prevention_test.go b/felix/fv/service_loop_prevention_test.go index d567fce84eb..b3c1a09fef6 100644 --- a/felix/fv/service_loop_prevention_test.go +++ b/felix/fv/service_loop_prevention_test.go @@ -50,7 +50,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ service loop prevention; wi if BPFMode() { options.EnableIPv6 = true } - options.IPIPEnabled = false + options.IPIPMode = api.IPIPModeNever tc, client = infrastructure.StartNNodeTopology(2, options, infra) if BPFMode() { ensureAllNodesBPFProgramsAttached(tc.Felixes) diff --git a/felix/fv/spoof_test.go b/felix/fv/spoof_test.go index 6a1b796e3c4..8a381a24c06 100644 --- a/felix/fv/spoof_test.go +++ b/felix/fv/spoof_test.go @@ -169,7 +169,7 @@ var _ = Describe("Spoof tests", func() { Expect(err).NotTo(HaveOccurred()) opts := infrastructure.DefaultTopologyOptions() opts.EnableIPv6 = true - opts.IPIPEnabled = false + opts.IPIPMode = api.IPIPModeNever opts.ExtraEnvVars["FELIX_BPFConnectTimeLoadBalancing"] = string(api.BPFConnectTimeLBDisabled) opts.ExtraEnvVars["FELIX_BPFHostNetworkedNATWithoutCTLB"] = string(api.BPFHostNetworkedNATEnabled) opts.ExtraEnvVars["FELIX_IPV6SUPPORT"] = "true" diff --git a/felix/fv/status_report_test.go b/felix/fv/status_report_test.go index 1ecfe78fbfd..2c13a817cad 100644 --- a/felix/fv/status_report_test.go +++ b/felix/fv/status_report_test.go @@ -49,7 +49,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ openstack status-reporting" topologyOptions := infrastructure.DefaultTopologyOptions() topologyOptions.VXLANMode = api.VXLANModeAlways - topologyOptions.IPIPEnabled = false + topologyOptions.IPIPMode = api.IPIPModeNever topologyOptions.EnableIPv6 = false topologyOptions.ExtraEnvVars["FELIX_ENDPOINTREPORTINGENABLED"] = "true" topologyOptions.ExtraEnvVars["FELIX_OPENSTACKREGION"] = "r0" diff --git a/felix/fv/tiered_policy_test.go b/felix/fv/tiered_policy_test.go index 23c3c3770e5..e4203e46572 100644 --- a/felix/fv/tiered_policy_test.go +++ b/felix/fv/tiered_policy_test.go @@ -81,7 +81,7 @@ var _ = infrastructure.DatastoreDescribe("connectivity tests with policy tiers _ BeforeEach(func() { infra = getInfra() opts = infrastructure.DefaultTopologyOptions() - opts.IPIPEnabled = false + opts.IPIPMode = api.IPIPModeNever // Start felix instances. tc, client = infrastructure.StartNNodeTopology(2, opts, infra) diff --git a/felix/fv/vxlan_test.go b/felix/fv/vxlan_test.go index f5bf6e46d67..3ea43021f08 100644 --- a/felix/fv/vxlan_test.go +++ b/felix/fv/vxlan_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2020-2021 Tigera, Inc. All rights reserved. +// Copyright (c) 2020-2024 Tigera, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -83,7 +83,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ VXLAN topology before addin Skip("Skipping NFT / BPF tests for etcdv3 backend.") } - topologyOptions = createBaseTopologyOptions(vxlanMode, enableIPv6, routeSource, brokenXSum) + topologyOptions = createVXLANBaseTopologyOptions(vxlanMode, enableIPv6, routeSource, brokenXSum) topologyOptions.FelixLogSeverity = "Debug" tc, client = infrastructure.StartNNodeTopology(3, topologyOptions, infra) @@ -875,10 +875,10 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ VXLAN topology before addin } }) -func createBaseTopologyOptions(vxlanMode api.VXLANMode, enableIPv6 bool, routeSource string, brokenXSum bool) infrastructure.TopologyOptions { +func createVXLANBaseTopologyOptions(vxlanMode api.VXLANMode, enableIPv6 bool, routeSource string, brokenXSum bool) infrastructure.TopologyOptions { topologyOptions := infrastructure.DefaultTopologyOptions() topologyOptions.VXLANMode = vxlanMode - topologyOptions.IPIPEnabled = false + topologyOptions.IPIPMode = api.IPIPModeNever topologyOptions.EnableIPv6 = enableIPv6 topologyOptions.ExtraEnvVars["FELIX_ROUTESOURCE"] = routeSource // We force the broken checksum handling on or off so that we're not dependent on kernel version diff --git a/felix/fv/wireguard_test.go b/felix/fv/wireguard_test.go index 8f97f06dff5..34b98c1650a 100644 --- a/felix/fv/wireguard_test.go +++ b/felix/fv/wireguard_test.go @@ -17,12 +17,10 @@ package fv_test import ( - "bytes" "context" "errors" "fmt" "os" - "os/exec" "regexp" "strconv" "strings" @@ -75,9 +73,9 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ WireGuard-Supported", []api cc *connectivity.Checker routeEntriesV4 [nodeCount]string routeEntriesV6 [nodeCount]string - dmesgCmd *exec.Cmd - dmesgBuf bytes.Buffer - dmesgKill func() + //dmesgCmd *exec.Cmd + //dmesgBuf bytes.Buffer + //dmesgKill func() wgBootstrapEvents chan struct{} ) @@ -108,17 +106,17 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ WireGuard-Supported", []api } // Enable Wireguard module debugging. - utils.Run("sudo", "sh", "-c", "echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control") + //utils.Run("sudo", "sh", "-c", "echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control") // Start a process tailing the dmesg log. - ctx, cancel := context.WithCancel(context.Background()) + /*ctx, cancel := context.WithCancel(context.Background()) dmesgCmd = exec.CommandContext(ctx, "sudo", "dmesg", "-wH") dmesgCmd.Stdout = &dmesgBuf dmesgCmd.Stderr = &dmesgBuf err := dmesgCmd.Start() Expect(err).NotTo(HaveOccurred()) dmesgKill = cancel - log.Info("Started dmesg log capture") + log.Info("Started dmesg log capture")*/ infra = getInfra() ipipEnabled := !BPFMode() || !wireguardEnabledV6 @@ -188,11 +186,11 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ WireGuard-Supported", []api }) AfterEach(func() { - if dmesgKill != nil { + /*if dmesgKill != nil { log.Info("Stop dmesg log capture") dmesgKill() log.Infof("Captured dmesg log:\n%v", dmesgBuf.String()) - } + }*/ if CurrentGinkgoTestDescription().Failed { for _, felix := range topologyContainers.Felixes { @@ -1057,7 +1055,7 @@ var _ = infrastructure.DatastoreDescribe("_BPF-SAFE_ WireGuard-Supported", []api } }) - It("workload connectivity remains but uses un-encrypted tunnel", func() { + It("nina workload connectivity remains but uses un-encrypted tunnel", func() { if wireguardEnabledV4 { cc.ExpectSome(wlsV4[0], wlsV4[1]) cc.ExpectSome(wlsV4[1], wlsV4[0]) @@ -1765,7 +1763,8 @@ func wireguardTopologyOptions(routeSource string, ipipEnabled, wireguardIPv4Enab // Enable IPv6 if IPv6 Wireguard will be enabled. topologyOptions.EnableIPv6 = wireguardIPv6Enabled // Assigning workload IPs using IPAM API. - topologyOptions.IPIPRoutesEnabled = false + //topologyOptions.SimulateRoutes = true + topologyOptions.IPIPMode = api.IPIPModeNever // Indicate wireguard is enabled topologyOptions.WireguardEnabled = wireguardIPv4Enabled topologyOptions.WireguardEnabledV6 = wireguardIPv6Enabled @@ -1775,7 +1774,10 @@ func wireguardTopologyOptions(routeSource string, ipipEnabled, wireguardIPv4Enab } topologyOptions.ExtraEnvVars["FELIX_ROUTESOURCE"] = routeSource topologyOptions.ExtraEnvVars["FELIX_PROMETHEUSMETRICSENABLED"] = "true" - topologyOptions.IPIPEnabled = ipipEnabled + if !ipipEnabled { + topologyOptions.IPIPMode = api.IPIPModeNever + topologyOptions.SimulateRoutes = true + } // With Wireguard and BPF mode the default IptablesMarkMask of 0xffff0000 isn't enough. topologyOptions.ExtraEnvVars["FELIX_IPTABLESMARKMASK"] = "4294934528" // 0xffff8000 diff --git a/felix/routetable/defs.go b/felix/routetable/defs.go index 094203e5908..2c9e256377f 100644 --- a/felix/routetable/defs.go +++ b/felix/routetable/defs.go @@ -38,6 +38,8 @@ const ( RouteClassWireguard RouteClassVXLANSameSubnet RouteClassVXLANTunnel + RouteClassIPIPTSameSubnet + RouteClassIPIPTTunnel RouteClassIPAMBlockDrop RouteClassMax @@ -45,7 +47,8 @@ const ( func (c RouteClass) IsRemote() bool { switch c { - case RouteClassVXLANTunnel, RouteClassVXLANSameSubnet, RouteClassWireguard: + case RouteClassVXLANTunnel, RouteClassVXLANSameSubnet, RouteClassWireguard, + RouteClassIPIPTTunnel, RouteClassIPIPTSameSubnet: return true default: return false @@ -115,7 +118,7 @@ func (t Target) RouteScope() netlink.Scope { case TargetTypeProhibit: return netlink.SCOPE_UNIVERSE case TargetTypeOnLink: - return netlink.SCOPE_LINK + return netlink.SCOPE_UNIVERSE default: return netlink.SCOPE_LINK } diff --git a/felix/routetable/ownershippol/main_route_table_policy.go b/felix/routetable/ownershippol/main_route_table_policy.go index 4480ade8d03..11f1d2dd95e 100644 --- a/felix/routetable/ownershippol/main_route_table_policy.go +++ b/felix/routetable/ownershippol/main_route_table_policy.go @@ -46,8 +46,8 @@ func NewMainTable( // So, if we see RTPROTO_BOOT on a route, it's ours if it's also // associated with one of our interfaces. But, if we see a route with // defaultVXLANProto, we know it's ours. - allRouteProtos = []netlink.RouteProtocol{unix.RTPROT_BOOT, dataplanedefs.VXLANDefaultProto} - exclusiveRouteProtos = []netlink.RouteProtocol{dataplanedefs.VXLANDefaultProto} + allRouteProtos = []netlink.RouteProtocol{unix.RTPROT_BOOT, dataplanedefs.DefaultRoutingProto} + exclusiveRouteProtos = []netlink.RouteProtocol{dataplanedefs.DefaultRoutingProto} } else { // If DeviceRouteProtocol is not RTPROTO_BOOT, then we use that value // for all our routes and we don't need to worry about RTPROTO_BOOT. @@ -62,6 +62,7 @@ func NewMainTable( // we'll clean up the routes if VXLAN is disabled. vxlanIfaceName, dataplanedefs.BPFInDev, + dataplanedefs.IPIPIfaceNameV4, // Not including routetable.InterfaceNone because MainTableOwnershipPolicy // automatically handles it. // Not including tunl0, it is managed by BIRD. diff --git a/felix/routetable/routeclass_string.go b/felix/routetable/routeclass_string.go index 7a3e95e94d6..c876191573f 100644 --- a/felix/routetable/routeclass_string.go +++ b/felix/routetable/routeclass_string.go @@ -13,13 +13,15 @@ func _() { _ = x[RouteClassWireguard-2] _ = x[RouteClassVXLANSameSubnet-3] _ = x[RouteClassVXLANTunnel-4] - _ = x[RouteClassIPAMBlockDrop-5] - _ = x[RouteClassMax-6] + _ = x[RouteClassIPIPTSameSubnet-5] + _ = x[RouteClassIPIPTTunnel-6] + _ = x[RouteClassIPAMBlockDrop-7] + _ = x[RouteClassMax-8] } -const _RouteClass_name = "RouteClassLocalWorkloadRouteClassBPFSpecialRouteClassWireguardRouteClassVXLANSameSubnetRouteClassVXLANTunnelRouteClassIPAMBlockDropRouteClassMax" +const _RouteClass_name = "RouteClassLocalWorkloadRouteClassBPFSpecialRouteClassWireguardRouteClassVXLANSameSubnetRouteClassVXLANTunnelRouteClassIPIPTSameSubnetRouteClassIPIPTTunnelRouteClassIPAMBlockDropRouteClassMax" -var _RouteClass_index = [...]uint8{0, 23, 43, 62, 87, 108, 131, 144} +var _RouteClass_index = [...]uint8{0, 23, 43, 62, 87, 108, 133, 154, 177, 190} func (i RouteClass) String() string { if i < 0 || i >= RouteClass(len(_RouteClass_index)-1) { diff --git a/libcalico-go/config/crd/crd.projectcalico.org_felixconfigurations.yaml b/libcalico-go/config/crd/crd.projectcalico.org_felixconfigurations.yaml index 8e54bd87a2f..c97d09864ff 100644 --- a/libcalico-go/config/crd/crd.projectcalico.org_felixconfigurations.yaml +++ b/libcalico-go/config/crd/crd.projectcalico.org_felixconfigurations.yaml @@ -962,6 +962,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when diff --git a/libcalico-go/lib/backend/syncersv1/updateprocessors/configurationprocessor_test.go b/libcalico-go/lib/backend/syncersv1/updateprocessors/configurationprocessor_test.go index 27d3c9d4c6c..51dfe623111 100644 --- a/libcalico-go/lib/backend/syncersv1/updateprocessors/configurationprocessor_test.go +++ b/libcalico-go/lib/backend/syncersv1/updateprocessors/configurationprocessor_test.go @@ -43,7 +43,7 @@ const ( ) const ( - numBaseFelixConfigs = 161 + numBaseFelixConfigs = 162 ) var _ = Describe("Test the generic configuration update processor and the concrete implementations", func() { diff --git a/manifests/calico-bpf.yaml b/manifests/calico-bpf.yaml index 2d6cb2f8c9c..99a7ee6998c 100644 --- a/manifests/calico-bpf.yaml +++ b/manifests/calico-bpf.yaml @@ -1974,6 +1974,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when @@ -7638,6 +7642,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: diff --git a/manifests/calico-etcd.yaml b/manifests/calico-etcd.yaml index 77f3598794e..1883ccdc947 100644 --- a/manifests/calico-etcd.yaml +++ b/manifests/calico-etcd.yaml @@ -435,6 +435,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: diff --git a/manifests/calico-ipip.yaml b/manifests/calico-ipip.yaml new file mode 100644 index 00000000000..86c1a936a50 --- /dev/null +++ b/manifests/calico-ipip.yaml @@ -0,0 +1,7812 @@ +--- +# Source: calico/templates/calico-kube-controllers.yaml +# This manifest creates a Pod Disruption Budget for Controller to allow K8s Cluster Autoscaler to evict + +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: calico-kube-controllers + namespace: kube-system + labels: + k8s-app: calico-kube-controllers +spec: + maxUnavailable: 1 + selector: + matchLabels: + k8s-app: calico-kube-controllers +--- +# Source: calico/templates/calico-kube-controllers.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: calico-kube-controllers + namespace: kube-system +--- +# Source: calico/templates/calico-node.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: calico-node + namespace: kube-system +--- +# Source: calico/templates/calico-node.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: calico-cni-plugin + namespace: kube-system +--- +# Source: calico/templates/calico-config.yaml +# This ConfigMap is used to configure a self-hosted Calico installation. +kind: ConfigMap +apiVersion: v1 +metadata: + name: calico-config + namespace: kube-system +data: + # Typha is disabled. + typha_service_name: "none" + # Configure the backend to use. + calico_backend: "ipip" + + # Configure the MTU to use for workload interfaces and tunnels. + # By default, MTU is auto-detected, and explicitly setting this field should not be required. + # You can override auto-detection by providing a non-zero value. + veth_mtu: "0" + + # The CNI network configuration to install on each node. The special + # values in this config will be automatically populated. + cni_network_config: |- + { + "name": "k8s-pod-network", + "cniVersion": "0.3.1", + "plugins": [ + { + "type": "calico", + "log_level": "info", + "log_file_path": "/var/log/calico/cni/cni.log", + "datastore_type": "kubernetes", + "nodename": "__KUBERNETES_NODE_NAME__", + "mtu": __CNI_MTU__, + "ipam": { + "type": "calico-ipam" + }, + "policy": { + "type": "k8s" + }, + "kubernetes": { + "kubeconfig": "__KUBECONFIG_FILEPATH__" + } + }, + { + "type": "portmap", + "snat": true, + "capabilities": {"portMappings": true} + }, + { + "type": "bandwidth", + "capabilities": {"bandwidth": true} + } + ] + } +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: bgpconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPConfiguration + listKind: BGPConfigurationList + plural: bgpconfigurations + singular: bgpconfiguration + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: BGPConfiguration contains the configuration for any BGP routing. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BGPConfigurationSpec contains the values of the BGP configuration. + properties: + asNumber: + description: 'ASNumber is the default AS number used by a node. [Default: + 64512]' + format: int32 + type: integer + bindMode: + description: |- + BindMode indicates whether to listen for BGP connections on all addresses (None) + or only on the node's canonical IP address Node.Spec.BGP.IPvXAddress (NodeIP). + Default behaviour is to listen for BGP connections on all addresses. + type: string + communities: + description: Communities is a list of BGP community values and their + arbitrary names for tagging routes. + items: + description: Community contains standard or large community value + and its name. + properties: + name: + description: Name given to community value. + type: string + value: + description: |- + Value must be of format `aa:nn` or `aa:nn:mm`. + For standard community use `aa:nn` format, where `aa` and `nn` are 16 bit number. + For large community use `aa:nn:mm` format, where `aa`, `nn` and `mm` are 32 bit number. + Where, `aa` is an AS Number, `nn` and `mm` are per-AS identifier. + pattern: ^(\d+):(\d+)$|^(\d+):(\d+):(\d+)$ + type: string + type: object + type: array + ignoredInterfaces: + description: IgnoredInterfaces indicates the network interfaces that + needs to be excluded when reading device routes. + items: + type: string + type: array + listenPort: + description: ListenPort is the port where BGP protocol should listen. + Defaults to 179 + maximum: 65535 + minimum: 1 + type: integer + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: INFO]' + type: string + nodeMeshMaxRestartTime: + description: |- + Time to allow for software restart for node-to-mesh peerings. When specified, this is configured + as the graceful restart timeout. When not specified, the BIRD default of 120s is used. + This field can only be set on the default BGPConfiguration instance and requires that NodeMesh is enabled + type: string + nodeMeshPassword: + description: |- + Optional BGP password for full node-to-mesh peerings. + This field can only be set on the default BGPConfiguration instance and requires that NodeMesh is enabled + properties: + secretKeyRef: + description: Selects a key of a secret in the node pod's namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + nodeToNodeMeshEnabled: + description: 'NodeToNodeMeshEnabled sets whether full node to node + BGP mesh is enabled. [Default: true]' + type: boolean + prefixAdvertisements: + description: PrefixAdvertisements contains per-prefix advertisement + configuration. + items: + description: PrefixAdvertisement configures advertisement properties + for the specified CIDR. + properties: + cidr: + description: CIDR for which properties should be advertised. + type: string + communities: + description: |- + Communities can be list of either community names already defined in `Specs.Communities` or community value of format `aa:nn` or `aa:nn:mm`. + For standard community use `aa:nn` format, where `aa` and `nn` are 16 bit number. + For large community use `aa:nn:mm` format, where `aa`, `nn` and `mm` are 32 bit number. + Where,`aa` is an AS Number, `nn` and `mm` are per-AS identifier. + items: + type: string + type: array + type: object + type: array + serviceClusterIPs: + description: |- + ServiceClusterIPs are the CIDR blocks from which service cluster IPs are allocated. + If specified, Calico will advertise these blocks, as well as any cluster IPs within them. + items: + description: ServiceClusterIPBlock represents a single allowed ClusterIP + CIDR block. + properties: + cidr: + type: string + type: object + type: array + serviceExternalIPs: + description: |- + ServiceExternalIPs are the CIDR blocks for Kubernetes Service External IPs. + Kubernetes Service ExternalIPs will only be advertised if they are within one of these blocks. + items: + description: ServiceExternalIPBlock represents a single allowed + External IP CIDR block. + properties: + cidr: + type: string + type: object + type: array + serviceLoadBalancerIPs: + description: |- + ServiceLoadBalancerIPs are the CIDR blocks for Kubernetes Service LoadBalancer IPs. + Kubernetes Service status.LoadBalancer.Ingress IPs will only be advertised if they are within one of these blocks. + items: + description: ServiceLoadBalancerIPBlock represents a single allowed + LoadBalancer IP CIDR block. + properties: + cidr: + type: string + type: object + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: bgpfilters.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPFilter + listKind: BGPFilterList + plural: bgpfilters + singular: bgpfilter + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BGPFilterSpec contains the IPv4 and IPv6 filter rules of + the BGP Filter. + properties: + exportV4: + description: The ordered set of IPv4 BGPFilter rules acting on exporting + routes to a peer. + items: + description: BGPFilterRuleV4 defines a BGP filter rule consisting + a single IPv4 CIDR block and a filter action for this CIDR. + properties: + action: + type: string + cidr: + type: string + interface: + type: string + matchOperator: + type: string + prefixLength: + properties: + max: + format: int32 + maximum: 32 + minimum: 0 + type: integer + min: + format: int32 + maximum: 32 + minimum: 0 + type: integer + type: object + source: + type: string + required: + - action + type: object + type: array + exportV6: + description: The ordered set of IPv6 BGPFilter rules acting on exporting + routes to a peer. + items: + description: BGPFilterRuleV6 defines a BGP filter rule consisting + a single IPv6 CIDR block and a filter action for this CIDR. + properties: + action: + type: string + cidr: + type: string + interface: + type: string + matchOperator: + type: string + prefixLength: + properties: + max: + format: int32 + maximum: 128 + minimum: 0 + type: integer + min: + format: int32 + maximum: 128 + minimum: 0 + type: integer + type: object + source: + type: string + required: + - action + type: object + type: array + importV4: + description: The ordered set of IPv4 BGPFilter rules acting on importing + routes from a peer. + items: + description: BGPFilterRuleV4 defines a BGP filter rule consisting + a single IPv4 CIDR block and a filter action for this CIDR. + properties: + action: + type: string + cidr: + type: string + interface: + type: string + matchOperator: + type: string + prefixLength: + properties: + max: + format: int32 + maximum: 32 + minimum: 0 + type: integer + min: + format: int32 + maximum: 32 + minimum: 0 + type: integer + type: object + source: + type: string + required: + - action + type: object + type: array + importV6: + description: The ordered set of IPv6 BGPFilter rules acting on importing + routes from a peer. + items: + description: BGPFilterRuleV6 defines a BGP filter rule consisting + a single IPv6 CIDR block and a filter action for this CIDR. + properties: + action: + type: string + cidr: + type: string + interface: + type: string + matchOperator: + type: string + prefixLength: + properties: + max: + format: int32 + maximum: 128 + minimum: 0 + type: integer + min: + format: int32 + maximum: 128 + minimum: 0 + type: integer + type: object + source: + type: string + required: + - action + type: object + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: bgppeers.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPPeer + listKind: BGPPeerList + plural: bgppeers + singular: bgppeer + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BGPPeerSpec contains the specification for a BGPPeer resource. + properties: + asNumber: + description: The AS Number of the peer. + format: int32 + type: integer + filters: + description: The ordered set of BGPFilters applied on this BGP peer. + items: + type: string + type: array + keepOriginalNextHop: + description: |- + Option to keep the original nexthop field when routes are sent to a BGP Peer. + Setting "true" configures the selected BGP Peers node to use the "next hop keep;" + instead of "next hop self;"(default) in the specific branch of the Node on "bird.cfg". + type: boolean + maxRestartTime: + description: |- + Time to allow for software restart. When specified, this is configured as the graceful + restart timeout. When not specified, the BIRD default of 120s is used. + type: string + node: + description: |- + The node name identifying the Calico node instance that is targeted by this peer. + If this is not set, and no nodeSelector is specified, then this BGP peer selects all + nodes in the cluster. + type: string + nodeSelector: + description: |- + Selector for the nodes that should have this peering. When this is set, the Node + field must be empty. + type: string + numAllowedLocalASNumbers: + description: |- + Maximum number of local AS numbers that are allowed in the AS path for received routes. + This removes BGP loop prevention and should only be used if absolutely necessary. + format: int32 + type: integer + password: + description: Optional BGP password for the peerings generated by this + BGPPeer resource. + properties: + secretKeyRef: + description: Selects a key of a secret in the node pod's namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + peerIP: + description: |- + The IP address of the peer followed by an optional port number to peer with. + If port number is given, format should be `[]:port` or `:` for IPv4. + If optional port number is not set, and this peer IP and ASNumber belongs to a calico/node + with ListenPort set in BGPConfiguration, then we use that port to peer. + type: string + peerSelector: + description: |- + Selector for the remote nodes to peer with. When this is set, the PeerIP and + ASNumber fields must be empty. For each peering between the local node and + selected remote nodes, we configure an IPv4 peering if both ends have + NodeBGPSpec.IPv4Address specified, and an IPv6 peering if both ends have + NodeBGPSpec.IPv6Address specified. The remote AS number comes from the remote + node's NodeBGPSpec.ASNumber, or the global default if that is not set. + type: string + reachableBy: + description: |- + Add an exact, i.e. /32, static route toward peer IP in order to prevent route flapping. + ReachableBy contains the address of the gateway which peer can be reached by. + type: string + sourceAddress: + description: |- + Specifies whether and how to configure a source address for the peerings generated by + this BGPPeer resource. Default value "UseNodeIP" means to configure the node IP as the + source address. "None" means not to configure a source address. + type: string + ttlSecurity: + description: |- + TTLSecurity enables the generalized TTL security mechanism (GTSM) which protects against spoofed packets by + ignoring received packets with a smaller than expected TTL value. The provided value is the number of hops + (edges) between the peers. + type: integer + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: blockaffinities.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BlockAffinity + listKind: BlockAffinityList + plural: blockaffinities + singular: blockaffinity + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: BlockAffinitySpec contains the specification for a BlockAffinity + resource. + properties: + cidr: + type: string + deleted: + description: |- + Deleted indicates that this block affinity is being deleted. + This field is a string for compatibility with older releases that + mistakenly treat this field as a string. + type: string + node: + type: string + state: + type: string + type: + type: string + required: + - cidr + - deleted + - node + - state + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: caliconodestatuses.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: CalicoNodeStatus + listKind: CalicoNodeStatusList + plural: caliconodestatuses + singular: caliconodestatus + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: CalicoNodeStatusSpec contains the specification for a CalicoNodeStatus + resource. + properties: + classes: + description: |- + Classes declares the types of information to monitor for this calico/node, + and allows for selective status reporting about certain subsets of information. + items: + type: string + type: array + node: + description: The node name identifies the Calico node instance for + node status. + type: string + updatePeriodSeconds: + description: |- + UpdatePeriodSeconds is the period at which CalicoNodeStatus should be updated. + Set to 0 to disable CalicoNodeStatus refresh. Maximum update period is one day. + format: int32 + type: integer + type: object + status: + description: |- + CalicoNodeStatusStatus defines the observed state of CalicoNodeStatus. + No validation needed for status since it is updated by Calico. + properties: + agent: + description: Agent holds agent status on the node. + properties: + birdV4: + description: BIRDV4 represents the latest observed status of bird4. + properties: + lastBootTime: + description: LastBootTime holds the value of lastBootTime + from bird.ctl output. + type: string + lastReconfigurationTime: + description: LastReconfigurationTime holds the value of lastReconfigTime + from bird.ctl output. + type: string + routerID: + description: Router ID used by bird. + type: string + state: + description: The state of the BGP Daemon. + type: string + version: + description: Version of the BGP daemon + type: string + type: object + birdV6: + description: BIRDV6 represents the latest observed status of bird6. + properties: + lastBootTime: + description: LastBootTime holds the value of lastBootTime + from bird.ctl output. + type: string + lastReconfigurationTime: + description: LastReconfigurationTime holds the value of lastReconfigTime + from bird.ctl output. + type: string + routerID: + description: Router ID used by bird. + type: string + state: + description: The state of the BGP Daemon. + type: string + version: + description: Version of the BGP daemon + type: string + type: object + type: object + bgp: + description: BGP holds node BGP status. + properties: + numberEstablishedV4: + description: The total number of IPv4 established bgp sessions. + type: integer + numberEstablishedV6: + description: The total number of IPv6 established bgp sessions. + type: integer + numberNotEstablishedV4: + description: The total number of IPv4 non-established bgp sessions. + type: integer + numberNotEstablishedV6: + description: The total number of IPv6 non-established bgp sessions. + type: integer + peersV4: + description: PeersV4 represents IPv4 BGP peers status on the node. + items: + description: CalicoNodePeer contains the status of BGP peers + on the node. + properties: + peerIP: + description: IP address of the peer whose condition we are + reporting. + type: string + since: + description: Since the state or reason last changed. + type: string + state: + description: State is the BGP session state. + type: string + type: + description: |- + Type indicates whether this peer is configured via the node-to-node mesh, + or via en explicit global or per-node BGPPeer object. + type: string + type: object + type: array + peersV6: + description: PeersV6 represents IPv6 BGP peers status on the node. + items: + description: CalicoNodePeer contains the status of BGP peers + on the node. + properties: + peerIP: + description: IP address of the peer whose condition we are + reporting. + type: string + since: + description: Since the state or reason last changed. + type: string + state: + description: State is the BGP session state. + type: string + type: + description: |- + Type indicates whether this peer is configured via the node-to-node mesh, + or via en explicit global or per-node BGPPeer object. + type: string + type: object + type: array + required: + - numberEstablishedV4 + - numberEstablishedV6 + - numberNotEstablishedV4 + - numberNotEstablishedV6 + type: object + lastUpdated: + description: |- + LastUpdated is a timestamp representing the server time when CalicoNodeStatus object + last updated. It is represented in RFC3339 form and is in UTC. + format: date-time + nullable: true + type: string + routes: + description: Routes reports routes known to the Calico BGP daemon + on the node. + properties: + routesV4: + description: RoutesV4 represents IPv4 routes on the node. + items: + description: CalicoNodeRoute contains the status of BGP routes + on the node. + properties: + destination: + description: Destination of the route. + type: string + gateway: + description: Gateway for the destination. + type: string + interface: + description: Interface for the destination + type: string + learnedFrom: + description: LearnedFrom contains information regarding + where this route originated. + properties: + peerIP: + description: If sourceType is NodeMesh or BGPPeer, IP + address of the router that sent us this route. + type: string + sourceType: + description: Type of the source where a route is learned + from. + type: string + type: object + type: + description: Type indicates if the route is being used for + forwarding or not. + type: string + type: object + type: array + routesV6: + description: RoutesV6 represents IPv6 routes on the node. + items: + description: CalicoNodeRoute contains the status of BGP routes + on the node. + properties: + destination: + description: Destination of the route. + type: string + gateway: + description: Gateway for the destination. + type: string + interface: + description: Interface for the destination + type: string + learnedFrom: + description: LearnedFrom contains information regarding + where this route originated. + properties: + peerIP: + description: If sourceType is NodeMesh or BGPPeer, IP + address of the router that sent us this route. + type: string + sourceType: + description: Type of the source where a route is learned + from. + type: string + type: object + type: + description: Type indicates if the route is being used for + forwarding or not. + type: string + type: object + type: array + type: object + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: clusterinformations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: ClusterInformation + listKind: ClusterInformationList + plural: clusterinformations + singular: clusterinformation + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ClusterInformation contains the cluster specific information. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ClusterInformationSpec contains the values of describing + the cluster. + properties: + calicoVersion: + description: CalicoVersion is the version of Calico that the cluster + is running + type: string + clusterGUID: + description: ClusterGUID is the GUID of the cluster + type: string + clusterType: + description: ClusterType describes the type of the cluster + type: string + datastoreReady: + description: |- + DatastoreReady is used during significant datastore migrations to signal to components + such as Felix that it should wait before accessing the datastore. + type: boolean + variant: + description: Variant declares which variant of Calico should be active. + type: string + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: felixconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: FelixConfiguration + listKind: FelixConfigurationList + plural: felixconfigurations + singular: felixconfiguration + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Felix Configuration contains the configuration for Felix. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: FelixConfigurationSpec contains the values of the Felix configuration. + properties: + allowIPIPPacketsFromWorkloads: + description: |- + AllowIPIPPacketsFromWorkloads controls whether Felix will add a rule to drop IPIP encapsulated traffic + from workloads. [Default: false] + type: boolean + allowVXLANPacketsFromWorkloads: + description: |- + AllowVXLANPacketsFromWorkloads controls whether Felix will add a rule to drop VXLAN encapsulated traffic + from workloads. [Default: false] + type: boolean + awsSrcDstCheck: + description: |- + AWSSrcDstCheck controls whether Felix will try to change the "source/dest check" setting on the EC2 instance + on which it is running. A value of "Disable" will try to disable the source/dest check. Disabling the check + allows for sending workload traffic without encapsulation within the same AWS subnet. + [Default: DoNothing] + enum: + - DoNothing + - Enable + - Disable + type: string + bpfCTLBLogFilter: + description: |- + BPFCTLBLogFilter specifies, what is logged by connect time load balancer when BPFLogLevel is + debug. Currently has to be specified as 'all' when BPFLogFilters is set + to see CTLB logs. + [Default: unset - means logs are emitted when BPFLogLevel id debug and BPFLogFilters not set.] + type: string + bpfConnectTimeLoadBalancing: + description: |- + BPFConnectTimeLoadBalancing when in BPF mode, controls whether Felix installs the connect-time load + balancer. The connect-time load balancer is required for the host to be able to reach Kubernetes services + and it improves the performance of pod-to-service connections.When set to TCP, connect time load balancing + is available only for services with TCP ports. [Default: TCP] + enum: + - TCP + - Enabled + - Disabled + type: string + bpfConnectTimeLoadBalancingEnabled: + description: |- + BPFConnectTimeLoadBalancingEnabled when in BPF mode, controls whether Felix installs the connection-time load + balancer. The connect-time load balancer is required for the host to be able to reach Kubernetes services + and it improves the performance of pod-to-service connections. The only reason to disable it is for debugging + purposes. + + Deprecated: Use BPFConnectTimeLoadBalancing [Default: true] + type: boolean + bpfConntrackLogLevel: + description: |- + BPFConntrackLogLevel controls the log level of the BPF conntrack cleanup program, which runs periodically + to clean up expired BPF conntrack entries. + [Default: Off]. + enum: + - "Off" + - Debug + type: string + bpfConntrackMode: + description: |- + BPFConntrackCleanupMode controls how BPF conntrack entries are cleaned up. `Auto` will use a BPF program if supported, + falling back to userspace if not. `Userspace` will always use the userspace cleanup code. `BPFProgram` will + always use the BPF program (failing if not supported). + [Default: Auto] + enum: + - Auto + - Userspace + - BPFProgram + type: string + bpfConntrackTimeouts: + description: |- + BPFConntrackTimers overrides the default values for the specified conntrack timer if + set. Each value can be either a duration or `Auto` to pick the value from + a Linux conntrack timeout. + + Configurable timers are: CreationGracePeriod, TCPSynSent, + TCPEstablished, TCPFinsSeen, TCPResetSeen, UDPTimeout, GenericTimeout, + ICMPTimeout. + + Unset values are replaced by the default values with a warning log for + incorrect values. + properties: + creationGracePeriod: + description: |2- + CreationGracePeriod gives a generic grace period to new connection + before they are considered for cleanup [Default: 10s]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + genericTimeout: + description: |- + GenericTimeout controls how long it takes before considering this + entry for cleanup after the connection became idle. If set to 'Auto', the + value from nf_conntrack_generic_timeout is used. If nil, Calico uses its + own default value. [Default: 10m]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + icmpTimeout: + description: |- + ICMPTimeout controls how long it takes before considering this + entry for cleanup after the connection became idle. If set to 'Auto', the + value from nf_conntrack_icmp_timeout is used. If nil, Calico uses its + own default value. [Default: 5s]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + tcpEstablished: + description: |- + TCPEstablished controls how long it takes before considering this entry for + cleanup after the connection became idle. If set to 'Auto', the + value from nf_conntrack_tcp_timeout_established is used. If nil, Calico uses + its own default value. [Default: 1h]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + tcpFinsSeen: + description: |- + TCPFinsSeen controls how long it takes before considering this entry for + cleanup after the connection was closed gracefully. If set to 'Auto', the + value from nf_conntrack_tcp_timeout_time_wait is used. If nil, Calico uses + its own default value. [Default: Auto]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + tcpResetSeen: + description: |- + TCPFinsSeen controls how long it takes before considering this entry for + cleanup after the connection was aborted. If nil, Calico uses its own + default value. [Default: 40s]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + tcpSynSent: + description: |- + TCPSynSent controls how long it takes before considering this entry for + cleanup after the last SYN without a response. If set to 'Auto', the + value from nf_conntrack_tcp_timeout_syn_sent is used. If nil, Calico uses + its own default value. [Default: 20s]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + udpTimeout: + description: |- + UDPTimeout controls how long it takes before considering this entry for + cleanup after the connection became idle. If nil, Calico uses its own + default value. [Default: 60s]. + pattern: ^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|Auto)$ + type: string + type: object + bpfDSROptoutCIDRs: + description: |- + BPFDSROptoutCIDRs is a list of CIDRs which are excluded from DSR. That is, clients + in those CIDRs will access service node ports as if BPFExternalServiceMode was set to + Tunnel. + items: + type: string + type: array + bpfDataIfacePattern: + description: |- + BPFDataIfacePattern is a regular expression that controls which interfaces Felix should attach BPF programs to + in order to catch traffic to/from the network. This needs to match the interfaces that Calico workload traffic + flows over as well as any interfaces that handle incoming traffic to nodeports and services from outside the + cluster. It should not match the workload interfaces (usually named cali...) or any other special device managed + by Calico itself (e.g., tunnels). + type: string + bpfDisableGROForIfaces: + description: |- + BPFDisableGROForIfaces is a regular expression that controls which interfaces Felix should disable the + Generic Receive Offload [GRO] option. It should not match the workload interfaces (usually named cali...). + type: string + bpfDisableUnprivileged: + description: |- + BPFDisableUnprivileged, if enabled, Felix sets the kernel.unprivileged_bpf_disabled sysctl to disable + unprivileged use of BPF. This ensures that unprivileged users cannot access Calico's BPF maps and + cannot insert their own BPF programs to interfere with Calico's. [Default: true] + type: boolean + bpfEnabled: + description: 'BPFEnabled, if enabled Felix will use the BPF dataplane. + [Default: false]' + type: boolean + bpfEnforceRPF: + description: |- + BPFEnforceRPF enforce strict RPF on all host interfaces with BPF programs regardless of + what is the per-interfaces or global setting. Possible values are Disabled, Strict + or Loose. [Default: Loose] + pattern: ^(?i)(Disabled|Strict|Loose)?$ + type: string + bpfExcludeCIDRsFromNAT: + description: |- + BPFExcludeCIDRsFromNAT is a list of CIDRs that are to be excluded from NAT + resolution so that host can handle them. A typical usecase is node local + DNS cache. + items: + type: string + type: array + bpfExportBufferSizeMB: + description: |- + BPFExportBufferSizeMB in BPF mode, controls the buffer size used for sending BPF events to felix. + [Default: 1] + type: integer + bpfExtToServiceConnmark: + description: |- + BPFExtToServiceConnmark in BPF mode, controls a 32bit mark that is set on connections from an + external client to a local service. This mark allows us to control how packets of that + connection are routed within the host and how is routing interpreted by RPF check. [Default: 0] + type: integer + bpfExternalServiceMode: + description: |- + BPFExternalServiceMode in BPF mode, controls how connections from outside the cluster to services (node ports + and cluster IPs) are forwarded to remote workloads. If set to "Tunnel" then both request and response traffic + is tunneled to the remote node. If set to "DSR", the request traffic is tunneled but the response traffic + is sent directly from the remote node. In "DSR" mode, the remote node appears to use the IP of the ingress + node; this requires a permissive L2 network. [Default: Tunnel] + pattern: ^(?i)(Tunnel|DSR)?$ + type: string + bpfForceTrackPacketsFromIfaces: + description: |- + BPFForceTrackPacketsFromIfaces in BPF mode, forces traffic from these interfaces + to skip Calico's iptables NOTRACK rule, allowing traffic from those interfaces to be + tracked by Linux conntrack. Should only be used for interfaces that are not used for + the Calico fabric. For example, a docker bridge device for non-Calico-networked + containers. [Default: docker+] + items: + type: string + type: array + bpfHostConntrackBypass: + description: |- + BPFHostConntrackBypass Controls whether to bypass Linux conntrack in BPF mode for + workloads and services. [Default: true - bypass Linux conntrack] + type: boolean + bpfHostNetworkedNATWithoutCTLB: + description: |- + BPFHostNetworkedNATWithoutCTLB when in BPF mode, controls whether Felix does a NAT without CTLB. This along with BPFConnectTimeLoadBalancing + determines the CTLB behavior. [Default: Enabled] + enum: + - Enabled + - Disabled + type: string + bpfKubeProxyEndpointSlicesEnabled: + description: |- + BPFKubeProxyEndpointSlicesEnabled is deprecated and has no effect. BPF + kube-proxy always accepts endpoint slices. This option will be removed in + the next release. + type: boolean + bpfKubeProxyIptablesCleanupEnabled: + description: |- + BPFKubeProxyIptablesCleanupEnabled, if enabled in BPF mode, Felix will proactively clean up the upstream + Kubernetes kube-proxy's iptables chains. Should only be enabled if kube-proxy is not running. [Default: true] + type: boolean + bpfKubeProxyMinSyncPeriod: + description: |- + BPFKubeProxyMinSyncPeriod, in BPF mode, controls the minimum time between updates to the dataplane for Felix's + embedded kube-proxy. Lower values give reduced set-up latency. Higher values reduce Felix CPU usage by + batching up more work. [Default: 1s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + bpfL3IfacePattern: + description: |- + BPFL3IfacePattern is a regular expression that allows to list tunnel devices like wireguard or vxlan (i.e., L3 devices) + in addition to BPFDataIfacePattern. That is, tunnel interfaces not created by Calico, that Calico workload traffic flows + over as well as any interfaces that handle incoming traffic to nodeports and services from outside the cluster. + type: string + bpfLogFilters: + additionalProperties: + type: string + description: |- + BPFLogFilters is a map of key=values where the value is + a pcap filter expression and the key is an interface name with 'all' + denoting all interfaces, 'weps' all workload endpoints and 'heps' all host + endpoints. + + When specified as an env var, it accepts a comma-separated list of + key=values. + [Default: unset - means all debug logs are emitted] + type: object + bpfLogLevel: + description: |- + BPFLogLevel controls the log level of the BPF programs when in BPF dataplane mode. One of "Off", "Info", or + "Debug". The logs are emitted to the BPF trace pipe, accessible with the command `tc exec bpf debug`. + [Default: Off]. + pattern: ^(?i)(Off|Info|Debug)?$ + type: string + bpfMapSizeConntrack: + description: |- + BPFMapSizeConntrack sets the size for the conntrack map. This map must be large enough to hold + an entry for each active connection. Warning: changing the size of the conntrack map can cause disruption. + type: integer + bpfMapSizeConntrackCleanupQueue: + description: |- + BPFMapSizeConntrackCleanupQueue sets the size for the map used to hold NAT conntrack entries that are queued + for cleanup. This should be big enough to hold all the NAT entries that expire within one cleanup interval. + minimum: 1 + type: integer + bpfMapSizeConntrackScaling: + description: |- + BPFMapSizeConntrackScaling controls whether and how we scale the conntrack map size depending + on its usage. 'Disabled' make the size stay at the default or whatever is set by + BPFMapSizeConntrack*. 'DoubleIfFull' doubles the size when the map is pretty much full even + after cleanups. [Default: DoubleIfFull] + pattern: ^(?i)(Disabled|DoubleIfFull)?$ + type: string + bpfMapSizeIPSets: + description: |- + BPFMapSizeIPSets sets the size for ipsets map. The IP sets map must be large enough to hold an entry + for each endpoint matched by every selector in the source/destination matches in network policy. Selectors + such as "all()" can result in large numbers of entries (one entry per endpoint in that case). + type: integer + bpfMapSizeIfState: + description: |- + BPFMapSizeIfState sets the size for ifstate map. The ifstate map must be large enough to hold an entry + for each device (host + workloads) on a host. + type: integer + bpfMapSizeNATAffinity: + description: |- + BPFMapSizeNATAffinity sets the size of the BPF map that stores the affinity of a connection (for services that + enable that feature. + type: integer + bpfMapSizeNATBackend: + description: |- + BPFMapSizeNATBackend sets the size for NAT back end map. + This is the total number of endpoints. This is mostly + more than the size of the number of services. + type: integer + bpfMapSizeNATFrontend: + description: |- + BPFMapSizeNATFrontend sets the size for NAT front end map. + FrontendMap should be large enough to hold an entry for each nodeport, + external IP and each port in each service. + type: integer + bpfMapSizePerCpuConntrack: + description: |- + BPFMapSizePerCPUConntrack determines the size of conntrack map based on the number of CPUs. If set to a + non-zero value, overrides BPFMapSizeConntrack with `BPFMapSizePerCPUConntrack * (Number of CPUs)`. + This map must be large enough to hold an entry for each active connection. Warning: changing the size of the + conntrack map can cause disruption. + type: integer + bpfMapSizeRoute: + description: |- + BPFMapSizeRoute sets the size for the routes map. The routes map should be large enough + to hold one entry per workload and a handful of entries per host (enough to cover its own IPs and + tunnel IPs). + type: integer + bpfPSNATPorts: + anyOf: + - type: integer + - type: string + description: |- + BPFPSNATPorts sets the range from which we randomly pick a port if there is a source port + collision. This should be within the ephemeral range as defined by RFC 6056 (1024–65535) and + preferably outside the ephemeral ranges used by common operating systems. Linux uses + 32768–60999, while others mostly use the IANA defined range 49152–65535. It is not necessarily + a problem if this range overlaps with the operating systems. Both ends of the range are + inclusive. [Default: 20000:29999] + pattern: ^.* + x-kubernetes-int-or-string: true + bpfPolicyDebugEnabled: + description: |- + BPFPolicyDebugEnabled when true, Felix records detailed information + about the BPF policy programs, which can be examined with the calico-bpf command-line tool. + type: boolean + bpfProfiling: + description: |- + BPFProfiling controls profiling of BPF programs. At the monent, it can be + Disabled or Enabled. [Default: Disabled] + enum: + - Enabled + - Disabled + type: string + bpfRedirectToPeer: + description: |- + BPFRedirectToPeer controls which whether it is allowed to forward straight to the + peer side of the workload devices. It is allowed for any host L2 devices by default + (L2Only), but it breaks TCP dump on the host side of workload device as it bypasses + it on ingress. Value of Enabled also allows redirection from L3 host devices like + IPIP tunnel or Wireguard directly to the peer side of the workload's device. This + makes redirection faster, however, it breaks tools like tcpdump on the peer side. + Use Enabled with caution. [Default: L2Only] + enum: + - Enabled + - Disabled + - L2Only + type: string + chainInsertMode: + description: |- + ChainInsertMode controls whether Felix hooks the kernel's top-level iptables chains by inserting a rule + at the top of the chain or by appending a rule at the bottom. insert is the safe default since it prevents + Calico's rules from being bypassed. If you switch to append mode, be sure that the other rules in the chains + signal acceptance by falling through to the Calico rules, otherwise the Calico policy will be bypassed. + [Default: insert] + pattern: ^(?i)(Insert|Append)?$ + type: string + dataplaneDriver: + description: |- + DataplaneDriver filename of the external dataplane driver to use. Only used if UseInternalDataplaneDriver + is set to false. + type: string + dataplaneWatchdogTimeout: + description: |- + DataplaneWatchdogTimeout is the readiness/liveness timeout used for Felix's (internal) dataplane driver. + Deprecated: replaced by the generic HealthTimeoutOverrides. + type: string + debugDisableLogDropping: + description: |- + DebugDisableLogDropping disables the dropping of log messages when the log buffer is full. This can + significantly impact performance if log write-out is a bottleneck. [Default: false] + type: boolean + debugHost: + description: |- + DebugHost is the host IP or hostname to bind the debug port to. Only used + if DebugPort is set. [Default:localhost] + type: string + debugMemoryProfilePath: + description: DebugMemoryProfilePath is the path to write the memory + profile to when triggered by signal. + type: string + debugPort: + description: |- + DebugPort if set, enables Felix's debug HTTP port, which allows memory and CPU profiles + to be retrieved. The debug port is not secure, it should not be exposed to the internet. + type: integer + debugSimulateCalcGraphHangAfter: + description: |- + DebugSimulateCalcGraphHangAfter is used to simulate a hang in the calculation graph after the specified duration. + This is useful in tests of the watchdog system only! + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + debugSimulateDataplaneApplyDelay: + description: |- + DebugSimulateDataplaneApplyDelay adds an artificial delay to every dataplane operation. This is useful for + simulating a heavily loaded system for test purposes only. + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + debugSimulateDataplaneHangAfter: + description: |- + DebugSimulateDataplaneHangAfter is used to simulate a hang in the dataplane after the specified duration. + This is useful in tests of the watchdog system only! + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + defaultEndpointToHostAction: + description: |- + DefaultEndpointToHostAction controls what happens to traffic that goes from a workload endpoint to the host + itself (after the endpoint's egress policy is applied). By default, Calico blocks traffic from workload + endpoints to the host itself with an iptables "DROP" action. If you want to allow some or all traffic from + endpoint to host, set this parameter to RETURN or ACCEPT. Use RETURN if you have your own rules in the iptables + "INPUT" chain; Calico will insert its rules at the top of that chain, then "RETURN" packets to the "INPUT" chain + once it has completed processing workload endpoint egress policy. Use ACCEPT to unconditionally accept packets + from workloads after processing workload endpoint egress policy. [Default: Drop] + pattern: ^(?i)(Drop|Accept|Return)?$ + type: string + deviceRouteProtocol: + description: |- + DeviceRouteProtocol controls the protocol to set on routes programmed by Felix. The protocol is an 8-bit label + used to identify the owner of the route. + type: integer + deviceRouteSourceAddress: + description: |- + DeviceRouteSourceAddress IPv4 address to set as the source hint for routes programmed by Felix. When not set + the source address for local traffic from host to workload will be determined by the kernel. + type: string + deviceRouteSourceAddressIPv6: + description: |- + DeviceRouteSourceAddressIPv6 IPv6 address to set as the source hint for routes programmed by Felix. When not set + the source address for local traffic from host to workload will be determined by the kernel. + type: string + disableConntrackInvalidCheck: + description: |- + DisableConntrackInvalidCheck disables the check for invalid connections in conntrack. While the conntrack + invalid check helps to detect malicious traffic, it can also cause issues with certain multi-NIC scenarios. + type: boolean + endpointReportingDelay: + description: |- + EndpointReportingDelay is the delay before Felix reports endpoint status to the datastore. This is only used + by the OpenStack integration. [Default: 1s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + endpointReportingEnabled: + description: |- + EndpointReportingEnabled controls whether Felix reports endpoint status to the datastore. This is only used + by the OpenStack integration. [Default: false] + type: boolean + endpointStatusPathPrefix: + description: |- + EndpointStatusPathPrefix is the path to the directory where endpoint status will be written. Endpoint status + file reporting is disabled if field is left empty. + + Chosen directory should match the directory used by the CNI plugin for PodStartupDelay. + [Default: /var/run/calico] + type: string + externalNodesList: + description: |- + ExternalNodesCIDRList is a list of CIDR's of external, non-Calico nodes from which VXLAN/IPIP overlay traffic + will be allowed. By default, external tunneled traffic is blocked to reduce attack surface. + items: + type: string + type: array + failsafeInboundHostPorts: + description: |- + FailsafeInboundHostPorts is a list of ProtoPort struct objects including UDP/TCP/SCTP ports and CIDRs that Felix will + allow incoming traffic to host endpoints on irrespective of the security policy. This is useful to avoid accidentally + cutting off a host with incorrect configuration. For backwards compatibility, if the protocol is not specified, + it defaults to "tcp". If a CIDR is not specified, it will allow traffic from all addresses. To disable all inbound host ports, + use the value "[]". The default value allows ssh access, DHCP, BGP, etcd and the Kubernetes API. + [Default: tcp:22, udp:68, tcp:179, tcp:2379, tcp:2380, tcp:5473, tcp:6443, tcp:6666, tcp:6667 ] + items: + description: ProtoPort is combination of protocol, port, and CIDR. + Protocol and port must be specified. + properties: + net: + type: string + port: + type: integer + protocol: + type: string + required: + - port + type: object + type: array + failsafeOutboundHostPorts: + description: |- + FailsafeOutboundHostPorts is a list of PortProto struct objects including UDP/TCP/SCTP ports and CIDRs that Felix + will allow outgoing traffic from host endpoints to irrespective of the security policy. This is useful to avoid accidentally + cutting off a host with incorrect configuration. For backwards compatibility, if the protocol is not specified, it defaults + to "tcp". If a CIDR is not specified, it will allow traffic from all addresses. To disable all outbound host ports, + use the value "[]". The default value opens etcd's standard ports to ensure that Felix does not get cut off from etcd + as well as allowing DHCP, DNS, BGP and the Kubernetes API. + [Default: udp:53, udp:67, tcp:179, tcp:2379, tcp:2380, tcp:5473, tcp:6443, tcp:6666, tcp:6667 ] + items: + description: ProtoPort is combination of protocol, port, and CIDR. + Protocol and port must be specified. + properties: + net: + type: string + port: + type: integer + protocol: + type: string + required: + - port + type: object + type: array + featureDetectOverride: + description: |- + FeatureDetectOverride is used to override feature detection based on auto-detected platform + capabilities. Values are specified in a comma separated list with no spaces, example; + "SNATFullyRandom=true,MASQFullyRandom=false,RestoreSupportsLock=". A value of "true" or "false" will + force enable/disable feature, empty or omitted values fall back to auto-detection. + pattern: ^([a-zA-Z0-9-_]+=(true|false|),)*([a-zA-Z0-9-_]+=(true|false|))?$ + type: string + featureGates: + description: |- + FeatureGates is used to enable or disable tech-preview Calico features. + Values are specified in a comma separated list with no spaces, example; + "BPFConnectTimeLoadBalancingWorkaround=enabled,XyZ=false". This is + used to enable features that are not fully production ready. + pattern: ^([a-zA-Z0-9-_]+=([^=]+),)*([a-zA-Z0-9-_]+=([^=]+))?$ + type: string + floatingIPs: + description: |- + FloatingIPs configures whether or not Felix will program non-OpenStack floating IP addresses. (OpenStack-derived + floating IPs are always programmed, regardless of this setting.) + enum: + - Enabled + - Disabled + type: string + flowLogsCollectorDebugTrace: + description: |- + When FlowLogsCollectorDebugTrace is set to true, enables the logs in the collector to be + printed in their entirety. + type: boolean + flowLogsFlushInterval: + description: FlowLogsFlushInterval configures the interval at which + Felix exports flow logs. + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + flowLogsGoldmaneServer: + description: FlowLogGoldmaneServer is the flow server endpoint to + which flow data should be published. + type: string + flowLogsMaxOriginalIPsIncluded: + description: FlowLogsMaxOriginalIPsIncluded specifies the number of + unique IP addresses (if relevant) that should be included in Flow + logs. + type: integer + genericXDPEnabled: + description: |- + GenericXDPEnabled enables Generic XDP so network cards that don't support XDP offload or driver + modes can use XDP. This is not recommended since it doesn't provide better performance than + iptables. [Default: false] + type: boolean + goGCThreshold: + description: |- + GoGCThreshold Sets the Go runtime's garbage collection threshold. I.e. the percentage that the heap is + allowed to grow before garbage collection is triggered. In general, doubling the value halves the CPU time + spent doing GC, but it also doubles peak GC memory overhead. A special value of -1 can be used + to disable GC entirely; this should only be used in conjunction with the GoMemoryLimitMB setting. + + This setting is overridden by the GOGC environment variable. + + [Default: 40] + type: integer + goMaxProcs: + description: |- + GoMaxProcs sets the maximum number of CPUs that the Go runtime will use concurrently. A value of -1 means + "use the system default"; typically the number of real CPUs on the system. + + this setting is overridden by the GOMAXPROCS environment variable. + + [Default: -1] + type: integer + goMemoryLimitMB: + description: |- + GoMemoryLimitMB sets a (soft) memory limit for the Go runtime in MB. The Go runtime will try to keep its memory + usage under the limit by triggering GC as needed. To avoid thrashing, it will exceed the limit if GC starts to + take more than 50% of the process's CPU time. A value of -1 disables the memory limit. + + Note that the memory limit, if used, must be considerably less than any hard resource limit set at the container + or pod level. This is because felix is not the only process that must run in the container or pod. + + This setting is overridden by the GOMEMLIMIT environment variable. + + [Default: -1] + type: integer + healthEnabled: + description: |- + HealthEnabled if set to true, enables Felix's health port, which provides readiness and liveness endpoints. + [Default: false] + type: boolean + healthHost: + description: 'HealthHost is the host that the health server should + bind to. [Default: localhost]' + type: string + healthPort: + description: 'HealthPort is the TCP port that the health server should + bind to. [Default: 9099]' + type: integer + healthTimeoutOverrides: + description: |- + HealthTimeoutOverrides allows the internal watchdog timeouts of individual subcomponents to be + overridden. This is useful for working around "false positive" liveness timeouts that can occur + in particularly stressful workloads or if CPU is constrained. For a list of active + subcomponents, see Felix's logs. + items: + properties: + name: + type: string + timeout: + type: string + required: + - name + - timeout + type: object + type: array + interfaceExclude: + description: |- + InterfaceExclude A comma-separated list of interface names that should be excluded when Felix is resolving + host endpoints. The default value ensures that Felix ignores Kubernetes' internal `kube-ipvs0` device. If you + want to exclude multiple interface names using a single value, the list supports regular expressions. For + regular expressions you must wrap the value with `/`. For example having values `/^kube/,veth1` will exclude + all interfaces that begin with `kube` and also the interface `veth1`. [Default: kube-ipvs0] + type: string + interfacePrefix: + description: |- + InterfacePrefix is the interface name prefix that identifies workload endpoints and so distinguishes + them from host endpoint interfaces. Note: in environments other than bare metal, the orchestrators + configure this appropriately. For example our Kubernetes and Docker integrations set the 'cali' value, + and our OpenStack integration sets the 'tap' value. [Default: cali] + type: string + interfaceRefreshInterval: + description: |- + InterfaceRefreshInterval is the period at which Felix rescans local interfaces to verify their state. + The rescan can be disabled by setting the interval to 0. + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + ipForwarding: + description: |- + IPForwarding controls whether Felix sets the host sysctls to enable IP forwarding. IP forwarding is required + when using Calico for workload networking. This should be disabled only on hosts where Calico is used solely for + host protection. In BPF mode, due to a kernel interaction, either IPForwarding must be enabled or BPFEnforceRPF + must be disabled. [Default: Enabled] + enum: + - Enabled + - Disabled + type: string + ipipEnabled: + description: |- + IPIPEnabled overrides whether Felix should configure an IPIP interface on the host. Optional as Felix + determines this based on the existing IP pools. [Default: nil (unset)] + type: boolean + ipipMTU: + description: |- + IPIPMTU controls the MTU to set on the IPIP tunnel device. Optional as Felix auto-detects the MTU based on the + MTU of the host's interfaces. [Default: 0 (auto-detect)] + type: integer + ipsetsRefreshInterval: + description: |- + IpsetsRefreshInterval controls the period at which Felix re-checks all IP sets to look for discrepancies. + Set to 0 to disable the periodic refresh. [Default: 90s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + iptablesBackend: + description: |- + IptablesBackend controls which backend of iptables will be used. The default is `Auto`. + + Warning: changing this on a running system can leave "orphaned" rules in the "other" backend. These + should be cleaned up to avoid confusing interactions. + pattern: ^(?i)(Auto|Legacy|NFT)?$ + type: string + iptablesFilterAllowAction: + description: |- + IptablesFilterAllowAction controls what happens to traffic that is accepted by a Felix policy chain in the + iptables filter table (which is used for "normal" policy). The default will immediately `Accept` the traffic. Use + `Return` to send the traffic back up to the system chains for further processing. + pattern: ^(?i)(Accept|Return)?$ + type: string + iptablesFilterDenyAction: + description: |- + IptablesFilterDenyAction controls what happens to traffic that is denied by network policy. By default Calico blocks traffic + with an iptables "DROP" action. If you want to use "REJECT" action instead you can configure it in here. + pattern: ^(?i)(Drop|Reject)?$ + type: string + iptablesLockFilePath: + description: |- + IptablesLockFilePath is the location of the iptables lock file. You may need to change this + if the lock file is not in its standard location (for example if you have mapped it into Felix's + container at a different path). [Default: /run/xtables.lock] + type: string + iptablesLockProbeInterval: + description: |- + IptablesLockProbeInterval when IptablesLockTimeout is enabled: the time that Felix will wait between + attempts to acquire the iptables lock if it is not available. Lower values make Felix more + responsive when the lock is contended, but use more CPU. [Default: 50ms] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + iptablesLockTimeout: + description: |- + IptablesLockTimeout is the time that Felix itself will wait for the iptables lock (rather than delegating the + lock handling to the `iptables` command). + + Deprecated: `iptables-restore` v1.8+ always takes the lock, so enabling this feature results in deadlock. + [Default: 0s disabled] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + iptablesMangleAllowAction: + description: |- + IptablesMangleAllowAction controls what happens to traffic that is accepted by a Felix policy chain in the + iptables mangle table (which is used for "pre-DNAT" policy). The default will immediately `Accept` the traffic. + Use `Return` to send the traffic back up to the system chains for further processing. + pattern: ^(?i)(Accept|Return)?$ + type: string + iptablesMarkMask: + description: |- + IptablesMarkMask is the mask that Felix selects its IPTables Mark bits from. Should be a 32 bit hexadecimal + number with at least 8 bits set, none of which clash with any other mark bits in use on the system. + [Default: 0xffff0000] + format: int32 + type: integer + iptablesNATOutgoingInterfaceFilter: + description: |- + This parameter can be used to limit the host interfaces on which Calico will apply SNAT to traffic leaving a + Calico IPAM pool with "NAT outgoing" enabled. This can be useful if you have a main data interface, where + traffic should be SNATted and a secondary device (such as the docker bridge) which is local to the host and + doesn't require SNAT. This parameter uses the iptables interface matching syntax, which allows + as a + wildcard. Most users will not need to set this. Example: if your data interfaces are eth0 and eth1 and you + want to exclude the docker bridge, you could set this to eth+ + type: string + iptablesPostWriteCheckInterval: + description: |- + IptablesPostWriteCheckInterval is the period after Felix has done a write + to the dataplane that it schedules an extra read back in order to check the write was not + clobbered by another process. This should only occur if another application on the system + doesn't respect the iptables lock. [Default: 1s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + iptablesRefreshInterval: + description: |- + IptablesRefreshInterval is the period at which Felix re-checks the IP sets + in the dataplane to ensure that no other process has accidentally broken Calico's rules. + Set to 0 to disable IP sets refresh. Note: the default for this value is lower than the + other refresh intervals as a workaround for a Linux kernel bug that was fixed in kernel + version 4.11. If you are using v4.11 or greater you may want to set this to, a higher value + to reduce Felix CPU usage. [Default: 10s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + ipv6Support: + description: IPv6Support controls whether Felix enables support for + IPv6 (if supported by the in-use dataplane). + type: boolean + kubeNodePortRanges: + description: |- + KubeNodePortRanges holds list of port ranges used for service node ports. Only used if felix detects kube-proxy running in ipvs mode. + Felix uses these ranges to separate host and workload traffic. [Default: 30000:32767]. + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + logDebugFilenameRegex: + description: |- + LogDebugFilenameRegex controls which source code files have their Debug log output included in the logs. + Only logs from files with names that match the given regular expression are included. The filter only applies + to Debug level logs. + type: string + logFilePath: + description: 'LogFilePath is the full path to the Felix log. Set to + none to disable file logging. [Default: /var/log/calico/felix.log]' + type: string + logPrefix: + description: 'LogPrefix is the log prefix that Felix uses when rendering + LOG rules. [Default: calico-packet]' + type: string + logSeverityFile: + description: 'LogSeverityFile is the log severity above which logs + are sent to the log file. [Default: Info]' + pattern: ^(?i)(Debug|Info|Warning|Error|Fatal)?$ + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: Info]' + pattern: ^(?i)(Debug|Info|Warning|Error|Fatal)?$ + type: string + logSeveritySys: + description: |- + LogSeveritySys is the log severity above which logs are sent to the syslog. Set to None for no logging to syslog. + [Default: Info] + pattern: ^(?i)(Debug|Info|Warning|Error|Fatal)?$ + type: string + maxIpsetSize: + description: |- + MaxIpsetSize is the maximum number of IP addresses that can be stored in an IP set. Not applicable + if using the nftables backend. + type: integer + metadataAddr: + description: |- + MetadataAddr is the IP address or domain name of the server that can answer VM queries for + cloud-init metadata. In OpenStack, this corresponds to the machine running nova-api (or in + Ubuntu, nova-api-metadata). A value of none (case-insensitive) means that Felix should not + set up any NAT rule for the metadata path. [Default: 127.0.0.1] + type: string + metadataPort: + description: |- + MetadataPort is the port of the metadata server. This, combined with global.MetadataAddr (if + not 'None'), is used to set up a NAT rule, from 169.254.169.254:80 to MetadataAddr:MetadataPort. + In most cases this should not need to be changed [Default: 8775]. + type: integer + mtuIfacePattern: + description: |- + MTUIfacePattern is a regular expression that controls which interfaces Felix should scan in order + to calculate the host's MTU. + This should not match workload interfaces (usually named cali...). + type: string + natOutgoingAddress: + description: |- + NATOutgoingAddress specifies an address to use when performing source NAT for traffic in a natOutgoing pool that + is leaving the network. By default the address used is an address on the interface the traffic is leaving on + (i.e. it uses the iptables MASQUERADE target). + type: string + natPortRange: + anyOf: + - type: integer + - type: string + description: |- + NATPortRange specifies the range of ports that is used for port mapping when doing outgoing NAT. When unset the default behavior of the + network stack is used. + pattern: ^.* + x-kubernetes-int-or-string: true + netlinkTimeout: + description: |- + NetlinkTimeout is the timeout when talking to the kernel over the netlink protocol, used for programming + routes, rules, and other kernel objects. [Default: 10s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + nfNetlinkBufSize: + description: |- + NfNetlinkBufSize controls the size of NFLOG messages that the kernel will try to send to Felix. NFLOG messages + are used to report flow verdicts from the kernel. Warning: currently increasing the value may cause errors + due to a bug in the netlink library. + type: string + nftablesFilterAllowAction: + description: |- + NftablesFilterAllowAction controls the nftables action that Felix uses to represent the "allow" policy verdict + in the filter table. The default is to `ACCEPT` the traffic, which is a terminal action. Alternatively, + `RETURN` can be used to return the traffic back to the top-level chain for further processing by your rules. + pattern: ^(?i)(Accept|Return)?$ + type: string + nftablesFilterDenyAction: + description: |- + NftablesFilterDenyAction controls what happens to traffic that is denied by network policy. By default, Calico + blocks traffic with a "drop" action. If you want to use a "reject" action instead you can configure it here. + pattern: ^(?i)(Drop|Reject)?$ + type: string + nftablesMangleAllowAction: + description: |- + NftablesMangleAllowAction controls the nftables action that Felix uses to represent the "allow" policy verdict + in the mangle table. The default is to `ACCEPT` the traffic, which is a terminal action. Alternatively, + `RETURN` can be used to return the traffic back to the top-level chain for further processing by your rules. + pattern: ^(?i)(Accept|Return)?$ + type: string + nftablesMarkMask: + description: |- + NftablesMarkMask is the mask that Felix selects its nftables Mark bits from. Should be a 32 bit hexadecimal + number with at least 8 bits set, none of which clash with any other mark bits in use on the system. + [Default: 0xffff0000] + format: int32 + type: integer + nftablesMode: + description: 'NFTablesMode configures nftables support in Felix. [Default: + Disabled]' + enum: + - Disabled + - Enabled + - Auto + type: string + nftablesRefreshInterval: + description: 'NftablesRefreshInterval controls the interval at which + Felix periodically refreshes the nftables rules. [Default: 90s]' + type: string + openstackRegion: + description: |- + OpenstackRegion is the name of the region that a particular Felix belongs to. In a multi-region + Calico/OpenStack deployment, this must be configured somehow for each Felix (here in the datamodel, + or in felix.cfg or the environment on each compute node), and must match the [calico] + openstack_region value configured in neutron.conf on each node. [Default: Empty] + type: string + policySyncPathPrefix: + description: |- + PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, + like Application layer policy. [Default: Empty] + type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string + prometheusGoMetricsEnabled: + description: |- + PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when + set to false. This reduces the number of metrics reported, reducing Prometheus load. [Default: true] + type: boolean + prometheusMetricsEnabled: + description: 'PrometheusMetricsEnabled enables the Prometheus metrics + server in Felix if set to true. [Default: false]' + type: boolean + prometheusMetricsHost: + description: 'PrometheusMetricsHost is the host that the Prometheus + metrics server should bind to. [Default: empty]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. [Default: 9091]' + type: integer + prometheusProcessMetricsEnabled: + description: |- + PrometheusProcessMetricsEnabled disables process metrics collection, which the Prometheus client does by default, when + set to false. This reduces the number of metrics reported, reducing Prometheus load. [Default: true] + type: boolean + prometheusWireGuardMetricsEnabled: + description: |- + PrometheusWireGuardMetricsEnabled disables wireguard metrics collection, which the Prometheus client does by default, when + set to false. This reduces the number of metrics reported, reducing Prometheus load. [Default: true] + type: boolean + removeExternalRoutes: + description: |- + RemoveExternalRoutes Controls whether Felix will remove unexpected routes to workload interfaces. Felix will + always clean up expected routes that use the configured DeviceRouteProtocol. To add your own routes, you must + use a distinct protocol (in addition to setting this field to false). + type: boolean + reportingInterval: + description: |- + ReportingInterval is the interval at which Felix reports its status into the datastore or 0 to disable. + Must be non-zero in OpenStack deployments. [Default: 30s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + reportingTTL: + description: 'ReportingTTL is the time-to-live setting for process-wide + status reports. [Default: 90s]' + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + routeRefreshInterval: + description: |- + RouteRefreshInterval is the period at which Felix re-checks the routes + in the dataplane to ensure that no other process has accidentally broken Calico's rules. + Set to 0 to disable route refresh. [Default: 90s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + routeSource: + description: |- + RouteSource configures where Felix gets its routing information. + - WorkloadIPs: use workload endpoints to construct routes. + - CalicoIPAM: the default - use IPAM data to construct routes. + pattern: ^(?i)(WorkloadIPs|CalicoIPAM)?$ + type: string + routeSyncDisabled: + description: |- + RouteSyncDisabled will disable all operations performed on the route table. Set to true to + run in network-policy mode only. + type: boolean + routeTableRange: + description: |- + Deprecated in favor of RouteTableRanges. + Calico programs additional Linux route tables for various purposes. + RouteTableRange specifies the indices of the route tables that Calico should use. + properties: + max: + type: integer + min: + type: integer + required: + - max + - min + type: object + routeTableRanges: + description: |- + Calico programs additional Linux route tables for various purposes. + RouteTableRanges specifies a set of table index ranges that Calico should use. + Deprecates`RouteTableRange`, overrides `RouteTableRange`. + items: + properties: + max: + type: integer + min: + type: integer + required: + - max + - min + type: object + type: array + serviceLoopPrevention: + description: |- + When service IP advertisement is enabled, prevent routing loops to service IPs that are + not in use, by dropping or rejecting packets that do not get DNAT'd by kube-proxy. + Unless set to "Disabled", in which case such routing loops continue to be allowed. + [Default: Drop] + pattern: ^(?i)(Drop|Reject|Disabled)?$ + type: string + sidecarAccelerationEnabled: + description: 'SidecarAccelerationEnabled enables experimental sidecar + acceleration [Default: false]' + type: boolean + usageReportingEnabled: + description: |- + UsageReportingEnabled reports anonymous Calico version number and cluster size to projectcalico.org. Logs warnings returned by the usage + server. For example, if a significant security vulnerability has been discovered in the version of Calico being used. [Default: true] + type: boolean + usageReportingInitialDelay: + description: 'UsageReportingInitialDelay controls the minimum delay + before Felix makes a report. [Default: 300s]' + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + usageReportingInterval: + description: 'UsageReportingInterval controls the interval at which + Felix makes reports. [Default: 86400s]' + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + useInternalDataplaneDriver: + description: |- + UseInternalDataplaneDriver, if true, Felix will use its internal dataplane programming logic. If false, it + will launch an external dataplane driver and communicate with it over protobuf. + type: boolean + vxlanEnabled: + description: |- + VXLANEnabled overrides whether Felix should create the VXLAN tunnel device for IPv4 VXLAN networking. + Optional as Felix determines this based on the existing IP pools. [Default: nil (unset)] + type: boolean + vxlanMTU: + description: |- + VXLANMTU is the MTU to set on the IPv4 VXLAN tunnel device. Optional as Felix auto-detects the MTU based on the + MTU of the host's interfaces. [Default: 0 (auto-detect)] + type: integer + vxlanMTUV6: + description: |- + VXLANMTUV6 is the MTU to set on the IPv6 VXLAN tunnel device. Optional as Felix auto-detects the MTU based on the + MTU of the host's interfaces. [Default: 0 (auto-detect)] + type: integer + vxlanPort: + description: 'VXLANPort is the UDP port number to use for VXLAN traffic. + [Default: 4789]' + type: integer + vxlanVNI: + description: |- + VXLANVNI is the VXLAN VNI to use for VXLAN traffic. You may need to change this if the default value is + in use on your system. [Default: 4096] + type: integer + windowsManageFirewallRules: + description: 'WindowsManageFirewallRules configures whether or not + Felix will program Windows Firewall rules (to allow inbound access + to its own metrics ports). [Default: Disabled]' + enum: + - Enabled + - Disabled + type: string + wireguardEnabled: + description: 'WireguardEnabled controls whether Wireguard is enabled + for IPv4 (encapsulating IPv4 traffic over an IPv4 underlay network). + [Default: false]' + type: boolean + wireguardEnabledV6: + description: 'WireguardEnabledV6 controls whether Wireguard is enabled + for IPv6 (encapsulating IPv6 traffic over an IPv6 underlay network). + [Default: false]' + type: boolean + wireguardHostEncryptionEnabled: + description: 'WireguardHostEncryptionEnabled controls whether Wireguard + host-to-host encryption is enabled. [Default: false]' + type: boolean + wireguardInterfaceName: + description: 'WireguardInterfaceName specifies the name to use for + the IPv4 Wireguard interface. [Default: wireguard.cali]' + type: string + wireguardInterfaceNameV6: + description: 'WireguardInterfaceNameV6 specifies the name to use for + the IPv6 Wireguard interface. [Default: wg-v6.cali]' + type: string + wireguardKeepAlive: + description: 'WireguardPersistentKeepAlive controls Wireguard PersistentKeepalive + option. Set 0 to disable. [Default: 0]' + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + wireguardListeningPort: + description: 'WireguardListeningPort controls the listening port used + by IPv4 Wireguard. [Default: 51820]' + type: integer + wireguardListeningPortV6: + description: 'WireguardListeningPortV6 controls the listening port + used by IPv6 Wireguard. [Default: 51821]' + type: integer + wireguardMTU: + description: 'WireguardMTU controls the MTU on the IPv4 Wireguard + interface. See Configuring MTU [Default: 1440]' + type: integer + wireguardMTUV6: + description: 'WireguardMTUV6 controls the MTU on the IPv6 Wireguard + interface. See Configuring MTU [Default: 1420]' + type: integer + wireguardRoutingRulePriority: + description: 'WireguardRoutingRulePriority controls the priority value + to use for the Wireguard routing rule. [Default: 99]' + type: integer + wireguardThreadingEnabled: + description: |- + WireguardThreadingEnabled controls whether Wireguard has Threaded NAPI enabled. [Default: false] + This increases the maximum number of packets a Wireguard interface can process. + Consider threaded NAPI only if you have high packets per second workloads that are causing dropping packets due to a saturated `softirq` CPU core. + There is a [known issue](https://lore.kernel.org/netdev/CALrw=nEoT2emQ0OAYCjM1d_6Xe_kNLSZ6dhjb5FxrLFYh4kozA@mail.gmail.com/T/) with this setting + that may cause NAPI to get stuck holding the global `rtnl_mutex` when a peer is removed. + Workaround: Make sure your Linux kernel [includes this patch](https://github.com/torvalds/linux/commit/56364c910691f6d10ba88c964c9041b9ab777bd6) to unwedge NAPI. + type: boolean + workloadSourceSpoofing: + description: |- + WorkloadSourceSpoofing controls whether pods can use the allowedSourcePrefixes annotation to send traffic with a source IP + address that is not theirs. This is disabled by default. When set to "Any", pods can request any prefix. + pattern: ^(?i)(Disabled|Any)?$ + type: string + xdpEnabled: + description: 'XDPEnabled enables XDP acceleration for suitable untracked + incoming deny rules. [Default: true]' + type: boolean + xdpRefreshInterval: + description: |- + XDPRefreshInterval is the period at which Felix re-checks all XDP state to ensure that no + other process has accidentally broken Calico's BPF maps or attached programs. Set to 0 to + disable XDP refresh. [Default: 90s] + pattern: ^([0-9]+(\\.[0-9]+)?(ms|s|m|h))*$ + type: string + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: globalnetworkpolicies.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: GlobalNetworkPolicy + listKind: GlobalNetworkPolicyList + plural: globalnetworkpolicies + singular: globalnetworkpolicy + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + applyOnForward: + description: ApplyOnForward indicates to apply the rules in this policy + on forward traffic. + type: boolean + doNotTrack: + description: |- + DoNotTrack indicates whether packets matched by the rules in this policy should go through + the data plane's connection tracking, such as Linux conntrack. If True, the rules in + this policy are applied before any data plane connection tracking, and packets allowed by + this policy are marked as not to be tracked. + type: boolean + egress: + description: |- + The ordered set of egress rules. Each rule contains a set of packet match criteria and + a corresponding action to apply. + items: + description: |- + A Rule encapsulates a set of match criteria and an action. Both selector-based security Policy + and security Profiles reference rules - separated out as a list of rules for both + ingress and egress packet matching. + + Each positive match criteria has a negated version, prefixed with "Not". All the match + criteria within a rule must be satisfied for a packet to match. A single rule can contain + the positive and negative version of a match and both must be satisfied for the rule to match. + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: |- + Methods is an optional field that restricts the rule to apply only to HTTP requests that use one of the listed + HTTP Methods (e.g. GET, PUT, etc.) + Multiple methods are OR'd together. + items: + type: string + type: array + paths: + description: |- + Paths is an optional field that restricts the rule to apply to HTTP requests that use one of the listed + HTTP Paths. + Multiple paths are OR'd together. + e.g: + - exact: /foo + - prefix: /bar + NOTE: Each entry may ONLY specify either a `exact` or a `prefix` match. The validator will check for it. + items: + description: |- + HTTPPath specifies an HTTP path to match. It may be either of the form: + exact: : which matches the path exactly or + prefix: : which matches the path prefix + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: |- + ICMP is an optional field that restricts the rule to apply to a specific type and + code of ICMP traffic. This should only be specified if the Protocol field is set to + "ICMP" or "ICMPv6". + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + ipVersion: + description: |- + IPVersion is an optional field that restricts the rule to only match a specific IP + version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: |- + Protocol is an optional field that restricts the rule to only apply to traffic of + a specific IP protocol. Required if any of the EntityRules contain Ports + (because ports only apply to certain protocols). + + Must be one of these string values: "TCP", "UDP", "ICMP", "ICMPv6", "SCTP", "UDPLite" + or an integer in the range 1-255. + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + ingress: + description: |- + The ordered set of ingress rules. Each rule contains a set of packet match criteria and + a corresponding action to apply. + items: + description: |- + A Rule encapsulates a set of match criteria and an action. Both selector-based security Policy + and security Profiles reference rules - separated out as a list of rules for both + ingress and egress packet matching. + + Each positive match criteria has a negated version, prefixed with "Not". All the match + criteria within a rule must be satisfied for a packet to match. A single rule can contain + the positive and negative version of a match and both must be satisfied for the rule to match. + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: |- + Methods is an optional field that restricts the rule to apply only to HTTP requests that use one of the listed + HTTP Methods (e.g. GET, PUT, etc.) + Multiple methods are OR'd together. + items: + type: string + type: array + paths: + description: |- + Paths is an optional field that restricts the rule to apply to HTTP requests that use one of the listed + HTTP Paths. + Multiple paths are OR'd together. + e.g: + - exact: /foo + - prefix: /bar + NOTE: Each entry may ONLY specify either a `exact` or a `prefix` match. The validator will check for it. + items: + description: |- + HTTPPath specifies an HTTP path to match. It may be either of the form: + exact: : which matches the path exactly or + prefix: : which matches the path prefix + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: |- + ICMP is an optional field that restricts the rule to apply to a specific type and + code of ICMP traffic. This should only be specified if the Protocol field is set to + "ICMP" or "ICMPv6". + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + ipVersion: + description: |- + IPVersion is an optional field that restricts the rule to only match a specific IP + version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: |- + Protocol is an optional field that restricts the rule to only apply to traffic of + a specific IP protocol. Required if any of the EntityRules contain Ports + (because ports only apply to certain protocols). + + Must be one of these string values: "TCP", "UDP", "ICMP", "ICMPv6", "SCTP", "UDPLite" + or an integer in the range 1-255. + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + namespaceSelector: + description: NamespaceSelector is an optional field for an expression + used to select a pod based on namespaces. + type: string + order: + description: |- + Order is an optional field that specifies the order in which the policy is applied. + Policies with higher "order" are applied after those with lower + order within the same tier. If the order is omitted, it may be considered to be "infinite" - i.e. the + policy will be applied last. Policies with identical order will be applied in + alphanumerical order based on the Policy "Name" within the tier. + type: number + performanceHints: + description: |- + PerformanceHints contains a list of hints to Calico's policy engine to + help process the policy more efficiently. Hints never change the + enforcement behaviour of the policy. + + Currently, the only available hint is "AssumeNeededOnEveryNode". When + that hint is set on a policy, Felix will act as if the policy matches + a local endpoint even if it does not. This is useful for "preloading" + any large static policies that are known to be used on every node. + If the policy is _not_ used on a particular node then the work + done to preload the policy (and to maintain it) is wasted. + items: + type: string + type: array + preDNAT: + description: PreDNAT indicates to apply the rules in this policy before + any DNAT. + type: boolean + selector: + description: "The selector is an expression used to pick out the endpoints + that the policy should\nbe applied to.\n\nSelector expressions follow + this syntax:\n\n\tlabel == \"string_literal\" -> comparison, e.g. + my_label == \"foo bar\"\n\tlabel != \"string_literal\" -> not + equal; also matches if label is not present\n\tlabel in { \"a\", + \"b\", \"c\", ... } -> true if the value of label X is one of + \"a\", \"b\", \"c\"\n\tlabel not in { \"a\", \"b\", \"c\", ... } + \ -> true if the value of label X is not one of \"a\", \"b\", \"c\"\n\thas(label_name) + \ -> True if that label is present\n\t! expr -> negation of expr\n\texpr + && expr -> Short-circuit and\n\texpr || expr -> Short-circuit + or\n\t( expr ) -> parens for grouping\n\tall() or the empty selector + -> matches all endpoints.\n\nLabel names are allowed to contain + alphanumerics, -, _ and /. String literals are more permissive\nbut + they do not support escape characters.\n\nExamples (with made-up + labels):\n\n\ttype == \"webserver\" && deployment == \"prod\"\n\ttype + in {\"frontend\", \"backend\"}\n\tdeployment != \"dev\"\n\t! has(label_name)" + type: string + serviceAccountSelector: + description: ServiceAccountSelector is an optional field for an expression + used to select a pod based on service accounts. + type: string + tier: + description: |- + The name of the tier that this policy belongs to. If this is omitted, the default + tier (name is "default") is assumed. The specified tier must exist in order to create + security policies within the tier, the "default" tier is created automatically if it + does not exist, this means for deployments requiring only a single Tier, the tier name + may be omitted on all policy management requests. + type: string + types: + description: |- + Types indicates whether this policy applies to ingress, or to egress, or to both. When + not explicitly specified (and so the value on creation is empty or nil), Calico defaults + Types according to what Ingress and Egress rules are present in the policy. The + default is: + + - [ PolicyTypeIngress ], if there are no Egress rules (including the case where there are + also no Ingress rules) + + - [ PolicyTypeEgress ], if there are Egress rules but no Ingress rules + + - [ PolicyTypeIngress, PolicyTypeEgress ], if there are both Ingress and Egress rules. + + When the policy is read back again, Types will always be one of these values, never empty + or nil. + items: + description: PolicyType enumerates the possible values of the PolicySpec + Types field. + type: string + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: globalnetworksets.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: GlobalNetworkSet + listKind: GlobalNetworkSetList + plural: globalnetworksets + singular: globalnetworkset + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: |- + GlobalNetworkSet contains a set of arbitrary IP sub-networks/CIDRs that share labels to + allow rules to refer to them via selectors. The labels of GlobalNetworkSet are not namespaced. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GlobalNetworkSetSpec contains the specification for a NetworkSet + resource. + properties: + nets: + description: The list of IP networks that belong to this set. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: hostendpoints.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: HostEndpoint + listKind: HostEndpointList + plural: hostendpoints + singular: hostendpoint + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: HostEndpointSpec contains the specification for a HostEndpoint + resource. + properties: + expectedIPs: + description: "The expected IP addresses (IPv4 and IPv6) of the endpoint.\nIf + \"InterfaceName\" is not present, Calico will look for an interface + matching any\nof the IPs in the list and apply policy to that.\nNote:\n\tWhen + using the selector match criteria in an ingress or egress security + Policy\n\tor Profile, Calico converts the selector into a set of + IP addresses. For host\n\tendpoints, the ExpectedIPs field is used + for that purpose. (If only the interface\n\tname is specified, Calico + does not learn the IPs of the interface for use in match\n\tcriteria.)" + items: + type: string + type: array + interfaceName: + description: |- + Either "*", or the name of a specific Linux interface to apply policy to; or empty. "*" + indicates that this HostEndpoint governs all traffic to, from or through the default + network namespace of the host named by the "Node" field; entering and leaving that + namespace via any interface, including those from/to non-host-networked local workloads. + + If InterfaceName is not "*", this HostEndpoint only governs traffic that enters or leaves + the host through the specific interface named by InterfaceName, or - when InterfaceName + is empty - through the specific interface that has one of the IPs in ExpectedIPs. + Therefore, when InterfaceName is empty, at least one expected IP must be specified. Only + external interfaces (such as "eth0") are supported here; it isn't possible for a + HostEndpoint to protect traffic through a specific local workload interface. + + Note: Only some kinds of policy are implemented for "*" HostEndpoints; initially just + pre-DNAT policy. Please check Calico documentation for the latest position. + type: string + node: + description: The node name identifying the Calico node instance. + type: string + ports: + description: Ports contains the endpoint's named ports, which may + be referenced in security policy rules. + items: + properties: + name: + type: string + port: + type: integer + protocol: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + required: + - name + - port + - protocol + type: object + type: array + profiles: + description: |- + A list of identifiers of security Profile objects that apply to this endpoint. Each + profile is applied in the order that they appear in this list. Profile rules are applied + after the selector-based security policy. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: ipamblocks.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMBlock + listKind: IPAMBlockList + plural: ipamblocks + singular: ipamblock + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IPAMBlockSpec contains the specification for an IPAMBlock + resource. + properties: + affinity: + description: |- + Affinity of the block, if this block has one. If set, it will be of the form + "host:". If not set, this block is not affine to a host. + type: string + allocations: + description: |- + Array of allocations in-use within this block. nil entries mean the allocation is free. + For non-nil entries at index i, the index is the ordinal of the allocation within this block + and the value is the index of the associated attributes in the Attributes array. + items: + type: integer + # TODO: This nullable is manually added in. We should update controller-gen + # to handle []*int properly itself. + nullable: true + type: array + attributes: + description: |- + Attributes is an array of arbitrary metadata associated with allocations in the block. To find + attributes for a given allocation, use the value of the allocation's entry in the Allocations array + as the index of the element in this array. + items: + properties: + handle_id: + type: string + secondary: + additionalProperties: + type: string + type: object + type: object + type: array + cidr: + description: The block's CIDR. + type: string + deleted: + description: |- + Deleted is an internal boolean used to workaround a limitation in the Kubernetes API whereby + deletion will not return a conflict error if the block has been updated. It should not be set manually. + type: boolean + sequenceNumber: + default: 0 + description: |- + We store a sequence number that is updated each time the block is written. + Each allocation will also store the sequence number of the block at the time of its creation. + When releasing an IP, passing the sequence number associated with the allocation allows us + to protect against a race condition and ensure the IP hasn't been released and re-allocated + since the release request. + format: int64 + type: integer + sequenceNumberForAllocation: + additionalProperties: + format: int64 + type: integer + description: |- + Map of allocated ordinal within the block to sequence number of the block at + the time of allocation. Kubernetes does not allow numerical keys for maps, so + the key is cast to a string. + type: object + strictAffinity: + description: StrictAffinity on the IPAMBlock is deprecated and no + longer used by the code. Use IPAMConfig StrictAffinity instead. + type: boolean + unallocated: + description: Unallocated is an ordered list of allocations which are + free in the block. + items: + type: integer + type: array + required: + - allocations + - attributes + - cidr + - strictAffinity + - unallocated + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: ipamconfigs.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMConfig + listKind: IPAMConfigList + plural: ipamconfigs + singular: ipamconfig + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IPAMConfigSpec contains the specification for an IPAMConfig + resource. + properties: + autoAllocateBlocks: + type: boolean + maxBlocksPerHost: + description: |- + MaxBlocksPerHost, if non-zero, is the max number of blocks that can be + affine to each host. + maximum: 2147483647 + minimum: 0 + type: integer + strictAffinity: + type: boolean + required: + - autoAllocateBlocks + - strictAffinity + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: ipamhandles.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMHandle + listKind: IPAMHandleList + plural: ipamhandles + singular: ipamhandle + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IPAMHandleSpec contains the specification for an IPAMHandle + resource. + properties: + block: + additionalProperties: + type: integer + type: object + deleted: + type: boolean + handleID: + type: string + required: + - block + - handleID + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: ippools.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPPool + listKind: IPPoolList + plural: ippools + singular: ippool + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IPPoolSpec contains the specification for an IPPool resource. + properties: + allowedUses: + description: |- + AllowedUse controls what the IP pool will be used for. If not specified or empty, defaults to + ["Tunnel", "Workload"] for back-compatibility + items: + type: string + type: array + assignmentMode: + description: Determines the mode how IP addresses should be assigned + from this pool + enum: + - Automatic + - Manual + type: string + blockSize: + description: The block size to use for IP address assignments from + this pool. Defaults to 26 for IPv4 and 122 for IPv6. + type: integer + cidr: + description: The pool CIDR. + type: string + disableBGPExport: + description: 'Disable exporting routes from this IP Pool''s CIDR over + BGP. [Default: false]' + type: boolean + disabled: + description: When disabled is true, Calico IPAM will not assign addresses + from this pool. + type: boolean + ipip: + description: |- + Deprecated: this field is only used for APIv1 backwards compatibility. + Setting this field is not allowed, this field is for internal use only. + properties: + enabled: + description: |- + When enabled is true, ipip tunneling will be used to deliver packets to + destinations within this pool. + type: boolean + mode: + description: |- + The IPIP mode. This can be one of "always" or "cross-subnet". A mode + of "always" will also use IPIP tunneling for routing to destination IP + addresses within this pool. A mode of "cross-subnet" will only use IPIP + tunneling when the destination node is on a different subnet to the + originating node. The default value (if not specified) is "always". + type: string + type: object + ipipMode: + description: |- + Contains configuration for IPIP tunneling for this pool. If not specified, + then this is defaulted to "Never" (i.e. IPIP tunneling is disabled). + type: string + nat-outgoing: + description: |- + Deprecated: this field is only used for APIv1 backwards compatibility. + Setting this field is not allowed, this field is for internal use only. + type: boolean + natOutgoing: + description: |- + When natOutgoing is true, packets sent from Calico networked containers in + this pool to destinations outside of this pool will be masqueraded. + type: boolean + nodeSelector: + description: Allows IPPool to allocate for a specific node by label + selector. + type: string + vxlanMode: + description: |- + Contains configuration for VXLAN tunneling for this pool. If not specified, + then this is defaulted to "Never" (i.e. VXLAN tunneling is disabled). + type: string + required: + - cidr + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: ipreservations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPReservation + listKind: IPReservationList + plural: ipreservations + singular: ipreservation + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: IPReservationSpec contains the specification for an IPReservation + resource. + properties: + reservedCIDRs: + description: ReservedCIDRs is a list of CIDRs and/or IP addresses + that Calico IPAM will exclude from new allocations. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: kubecontrollersconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: KubeControllersConfiguration + listKind: KubeControllersConfigurationList + plural: kubecontrollersconfigurations + singular: kubecontrollersconfiguration + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: KubeControllersConfigurationSpec contains the values of the + Kubernetes controllers configuration. + properties: + controllers: + description: Controllers enables and configures individual Kubernetes + controllers + properties: + loadBalancer: + description: LoadBalancer enables and configures the LoadBalancer + controller. Enabled by default, set to nil to disable. + properties: + assignIPs: + type: string + type: object + namespace: + description: Namespace enables and configures the namespace controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + node: + description: Node enables and configures the node controller. + Enabled by default, set to nil to disable. + properties: + hostEndpoint: + description: HostEndpoint controls syncing nodes to host endpoints. + Disabled by default, set to nil to disable. + properties: + autoCreate: + description: 'AutoCreate enables automatic creation of + host endpoints for every node. [Default: Disabled]' + type: string + type: object + leakGracePeriod: + description: |- + LeakGracePeriod is the period used by the controller to determine if an IP address has been leaked. + Set to 0 to disable IP garbage collection. [Default: 15m] + type: string + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + syncLabels: + description: 'SyncLabels controls whether to copy Kubernetes + node labels to Calico nodes. [Default: Enabled]' + type: string + type: object + policy: + description: Policy enables and configures the policy controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + serviceAccount: + description: ServiceAccount enables and configures the service + account controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + workloadEndpoint: + description: WorkloadEndpoint enables and configures the workload + endpoint controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + type: object + debugProfilePort: + description: |- + DebugProfilePort configures the port to serve memory and cpu profiles on. If not specified, profiling + is disabled. + format: int32 + type: integer + etcdV3CompactionPeriod: + description: 'EtcdV3CompactionPeriod is the period between etcdv3 + compaction requests. Set to 0 to disable. [Default: 10m]' + type: string + healthChecks: + description: 'HealthChecks enables or disables support for health + checks [Default: Enabled]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: Info]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. Set to 0 to disable. [Default: 9094]' + type: integer + required: + - controllers + type: object + status: + description: |- + KubeControllersConfigurationStatus represents the status of the configuration. It's useful for admins to + be able to see the actual config that was applied, which can be modified by environment variables on the + kube-controllers process. + properties: + environmentVars: + additionalProperties: + type: string + description: |- + EnvironmentVars contains the environment variables on the kube-controllers that influenced + the RunningConfig. + type: object + runningConfig: + description: |- + RunningConfig contains the effective config that is running in the kube-controllers pod, after + merging the API resource with any environment variables. + properties: + controllers: + description: Controllers enables and configures individual Kubernetes + controllers + properties: + loadBalancer: + description: LoadBalancer enables and configures the LoadBalancer + controller. Enabled by default, set to nil to disable. + properties: + assignIPs: + type: string + type: object + namespace: + description: Namespace enables and configures the namespace + controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + node: + description: Node enables and configures the node controller. + Enabled by default, set to nil to disable. + properties: + hostEndpoint: + description: HostEndpoint controls syncing nodes to host + endpoints. Disabled by default, set to nil to disable. + properties: + autoCreate: + description: 'AutoCreate enables automatic creation + of host endpoints for every node. [Default: Disabled]' + type: string + type: object + leakGracePeriod: + description: |- + LeakGracePeriod is the period used by the controller to determine if an IP address has been leaked. + Set to 0 to disable IP garbage collection. [Default: 15m] + type: string + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + syncLabels: + description: 'SyncLabels controls whether to copy Kubernetes + node labels to Calico nodes. [Default: Enabled]' + type: string + type: object + policy: + description: Policy enables and configures the policy controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + serviceAccount: + description: ServiceAccount enables and configures the service + account controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + workloadEndpoint: + description: WorkloadEndpoint enables and configures the workload + endpoint controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + type: object + debugProfilePort: + description: |- + DebugProfilePort configures the port to serve memory and cpu profiles on. If not specified, profiling + is disabled. + format: int32 + type: integer + etcdV3CompactionPeriod: + description: 'EtcdV3CompactionPeriod is the period between etcdv3 + compaction requests. Set to 0 to disable. [Default: 10m]' + type: string + healthChecks: + description: 'HealthChecks enables or disables support for health + checks [Default: Enabled]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which + logs are sent to the stdout. [Default: Info]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. Set to 0 to disable. [Default: + 9094]' + type: integer + required: + - controllers + type: object + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: networkpolicies.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: NetworkPolicy + listKind: NetworkPolicyList + plural: networkpolicies + singular: networkpolicy + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + egress: + description: |- + The ordered set of egress rules. Each rule contains a set of packet match criteria and + a corresponding action to apply. + items: + description: |- + A Rule encapsulates a set of match criteria and an action. Both selector-based security Policy + and security Profiles reference rules - separated out as a list of rules for both + ingress and egress packet matching. + + Each positive match criteria has a negated version, prefixed with "Not". All the match + criteria within a rule must be satisfied for a packet to match. A single rule can contain + the positive and negative version of a match and both must be satisfied for the rule to match. + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: |- + Methods is an optional field that restricts the rule to apply only to HTTP requests that use one of the listed + HTTP Methods (e.g. GET, PUT, etc.) + Multiple methods are OR'd together. + items: + type: string + type: array + paths: + description: |- + Paths is an optional field that restricts the rule to apply to HTTP requests that use one of the listed + HTTP Paths. + Multiple paths are OR'd together. + e.g: + - exact: /foo + - prefix: /bar + NOTE: Each entry may ONLY specify either a `exact` or a `prefix` match. The validator will check for it. + items: + description: |- + HTTPPath specifies an HTTP path to match. It may be either of the form: + exact: : which matches the path exactly or + prefix: : which matches the path prefix + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: |- + ICMP is an optional field that restricts the rule to apply to a specific type and + code of ICMP traffic. This should only be specified if the Protocol field is set to + "ICMP" or "ICMPv6". + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + ipVersion: + description: |- + IPVersion is an optional field that restricts the rule to only match a specific IP + version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: |- + Protocol is an optional field that restricts the rule to only apply to traffic of + a specific IP protocol. Required if any of the EntityRules contain Ports + (because ports only apply to certain protocols). + + Must be one of these string values: "TCP", "UDP", "ICMP", "ICMPv6", "SCTP", "UDPLite" + or an integer in the range 1-255. + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + ingress: + description: |- + The ordered set of ingress rules. Each rule contains a set of packet match criteria and + a corresponding action to apply. + items: + description: |- + A Rule encapsulates a set of match criteria and an action. Both selector-based security Policy + and security Profiles reference rules - separated out as a list of rules for both + ingress and egress packet matching. + + Each positive match criteria has a negated version, prefixed with "Not". All the match + criteria within a rule must be satisfied for a packet to match. A single rule can contain + the positive and negative version of a match and both must be satisfied for the rule to match. + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: |- + Methods is an optional field that restricts the rule to apply only to HTTP requests that use one of the listed + HTTP Methods (e.g. GET, PUT, etc.) + Multiple methods are OR'd together. + items: + type: string + type: array + paths: + description: |- + Paths is an optional field that restricts the rule to apply to HTTP requests that use one of the listed + HTTP Paths. + Multiple paths are OR'd together. + e.g: + - exact: /foo + - prefix: /bar + NOTE: Each entry may ONLY specify either a `exact` or a `prefix` match. The validator will check for it. + items: + description: |- + HTTPPath specifies an HTTP path to match. It may be either of the form: + exact: : which matches the path exactly or + prefix: : which matches the path prefix + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: |- + ICMP is an optional field that restricts the rule to apply to a specific type and + code of ICMP traffic. This should only be specified if the Protocol field is set to + "ICMP" or "ICMPv6". + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + ipVersion: + description: |- + IPVersion is an optional field that restricts the rule to only match a specific IP + version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: |- + Match on a specific ICMP code. If specified, the Type value must also be specified. + This is a technical limitation imposed by the kernel's iptables firewall, which + Calico uses to enforce the rule. + type: integer + type: + description: |- + Match on a specific ICMP type. For example a value of 8 refers to ICMP Echo Request + (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: |- + Protocol is an optional field that restricts the rule to only apply to traffic of + a specific IP protocol. Required if any of the EntityRules contain Ports + (because ports only apply to certain protocols). + + Must be one of these string values: "TCP", "UDP", "ICMP", "ICMPv6", "SCTP", "UDPLite" + or an integer in the range 1-255. + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: |- + NamespaceSelector is an optional field that contains a selector expression. Only traffic + that originates from (or terminates at) endpoints within the selected namespaces will be + matched. When both NamespaceSelector and another selector are defined on the same rule, then only + workload endpoints that are matched by both selectors will be selected by the rule. + + For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting + only workload endpoints in the same namespace as the NetworkPolicy. + + For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting + only GlobalNetworkSet or HostEndpoint. + + For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload + endpoints across all namespaces. + type: string + nets: + description: |- + Nets is an optional field that restricts the rule to only apply to traffic that + originates from (or terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: |- + NotPorts is the negated version of the Ports field. + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: |- + NotSelector is the negated version of the Selector field. See Selector field for + subtleties with negated selectors. + type: string + ports: + description: |- + Ports is an optional field that restricts the rule to only apply to traffic that has a + source (destination) port that matches one of these ranges/values. This value is a + list of integers or strings that represent ranges of ports. + + Since only some protocols have ports, if any ports are specified it requires the + Protocol match in the Rule to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for\nsample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching\nthe selector will be matched.\n\nNote that: + in addition to the negated version of the Selector (see + NotSelector below), the\nselector expression syntax itself + supports negation. The two types of negation are subtly\ndifferent. + One negates the set of matched endpoints, the other negates + the whole match:\n\n\tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled\n\tendpoints + that do not have the label \"my_label\".\n\n\tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled\n\tendpoints that do have the label + \"my_label\".\n\nThe effect is that the latter will accept + packets from non-Calico sources whereas the\nformer is + limited to packets from Calico-controlled endpoints." + type: string + serviceAccounts: + description: |- + ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or + terminates at) a pod running as a matching service account. + properties: + names: + description: |- + Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates + at) a pod running as a service account whose name is in the list. + items: + type: string + type: array + selector: + description: |- + Selector is an optional field that restricts the rule to only apply to traffic that originates from + (or terminates at) a pod running as a service account that matches the given label selector. + If both Names and Selector are specified then they are AND'ed. + type: string + type: object + services: + description: |- + Services is an optional field that contains options for matching Kubernetes Services. + If specified, only traffic that originates from or terminates at endpoints within the selected + service(s) will be matched, and only to/from each endpoint's port. + + Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, + NotNets or ServiceAccounts. + + Ports and NotPorts can only be specified with Services on ingress rules. + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: |- + Namespace specifies the namespace of the given Service. If left empty, the rule + will match within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + order: + description: |- + Order is an optional field that specifies the order in which the policy is applied. + Policies with higher "order" are applied after those with lower + order within the same tier. If the order is omitted, it may be considered to be "infinite" - i.e. the + policy will be applied last. Policies with identical order will be applied in + alphanumerical order based on the Policy "Name" within the tier. + type: number + performanceHints: + description: |- + PerformanceHints contains a list of hints to Calico's policy engine to + help process the policy more efficiently. Hints never change the + enforcement behaviour of the policy. + + Currently, the only available hint is "AssumeNeededOnEveryNode". When + that hint is set on a policy, Felix will act as if the policy matches + a local endpoint even if it does not. This is useful for "preloading" + any large static policies that are known to be used on every node. + If the policy is _not_ used on a particular node then the work + done to preload the policy (and to maintain it) is wasted. + items: + type: string + type: array + selector: + description: "The selector is an expression used to pick out the endpoints + that the policy should\nbe applied to.\n\nSelector expressions follow + this syntax:\n\n\tlabel == \"string_literal\" -> comparison, e.g. + my_label == \"foo bar\"\n\tlabel != \"string_literal\" -> not + equal; also matches if label is not present\n\tlabel in { \"a\", + \"b\", \"c\", ... } -> true if the value of label X is one of + \"a\", \"b\", \"c\"\n\tlabel not in { \"a\", \"b\", \"c\", ... } + \ -> true if the value of label X is not one of \"a\", \"b\", \"c\"\n\thas(label_name) + \ -> True if that label is present\n\t! expr -> negation of expr\n\texpr + && expr -> Short-circuit and\n\texpr || expr -> Short-circuit + or\n\t( expr ) -> parens for grouping\n\tall() or the empty selector + -> matches all endpoints.\n\nLabel names are allowed to contain + alphanumerics, -, _ and /. String literals are more permissive\nbut + they do not support escape characters.\n\nExamples (with made-up + labels):\n\n\ttype == \"webserver\" && deployment == \"prod\"\n\ttype + in {\"frontend\", \"backend\"}\n\tdeployment != \"dev\"\n\t! has(label_name)" + type: string + serviceAccountSelector: + description: ServiceAccountSelector is an optional field for an expression + used to select a pod based on service accounts. + type: string + tier: + description: |- + The name of the tier that this policy belongs to. If this is omitted, the default + tier (name is "default") is assumed. The specified tier must exist in order to create + security policies within the tier, the "default" tier is created automatically if it + does not exist, this means for deployments requiring only a single Tier, the tier name + may be omitted on all policy management requests. + type: string + types: + description: |- + Types indicates whether this policy applies to ingress, or to egress, or to both. When + not explicitly specified (and so the value on creation is empty or nil), Calico defaults + Types according to what Ingress and Egress are present in the policy. The + default is: + + - [ PolicyTypeIngress ], if there are no Egress rules (including the case where there are + also no Ingress rules) + + - [ PolicyTypeEgress ], if there are Egress rules but no Ingress rules + + - [ PolicyTypeIngress, PolicyTypeEgress ], if there are both Ingress and Egress rules. + + When the policy is read back again, Types will always be one of these values, never empty + or nil. + items: + description: PolicyType enumerates the possible values of the PolicySpec + Types field. + type: string + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: networksets.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: NetworkSet + listKind: NetworkSetList + plural: networksets + singular: networkset + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: NetworkSet is the Namespaced-equivalent of the GlobalNetworkSet. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: NetworkSetSpec contains the specification for a NetworkSet + resource. + properties: + nets: + description: The list of IP networks that belong to this set. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: tiers.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: Tier + listKind: TierList + plural: tiers + singular: tier + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: TierSpec contains the specification for a security policy + tier resource. + properties: + defaultAction: + description: |- + DefaultAction specifies the action applied to workloads selected by a policy in the tier, + but not rule matched the workload's traffic. + [Default: Deny] + enum: + - Pass + - Deny + type: string + order: + description: |- + Order is an optional field that specifies the order in which the tier is applied. + Tiers with higher "order" are applied after those with lower order. If the order + is omitted, it may be considered to be "infinite" - i.e. the tier will be applied + last. Tiers with identical order will be applied in alphanumerical order based + on the Tier "Name". + type: number + type: object + type: object + served: true + storage: true +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: experimental + creationTimestamp: null + name: adminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: AdminNetworkPolicy + listKind: AdminNetworkPolicyList + plural: adminnetworkpolicies + shortNames: + - anp + singular: adminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.priority + name: Priority + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + AdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of AdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of egress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + ANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a AdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + namedPort: + description: |- + NamedPort selects a port on a pod(s) based on name. + + + Support: Extended + + + + type: string + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the List of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + Exactly one of the selector pointers must be set for a given peer. If a + consumer observes none of its fields are set, they must assume an unknown + option has been specified and fail closed. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + networks: + description: |- + Networks defines a way to select peers via CIDR blocks. + This is intended for representing entities that live outside the cluster, + which can't be selected by pods, namespaces and nodes peers, but note + that cluster-internal traffic will be checked against the rule as + well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow + or deny all IPv4 pod-to-pod traffic as well. If you don't want that, + add a rule that Passes all pod traffic before the Networks rule. + + + Each item in Networks should be provided in the CIDR format and should be + IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8". + + + Networks can have upto 25 CIDRs specified. + + + Support: Extended + + + + items: + description: |- + CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8"). + This string must be validated by implementations using net.ParseCIDR + TODO: Introduce CEL CIDR validation regex isCIDR() in Kube 1.31 when it is available. + maxLength: 43 + type: string + x-kubernetes-validations: + - message: CIDR must be either an IPv4 or IPv6 address. + IPv4 address embedded in IPv6 addresses are not + supported + rule: self.contains(':') != self.contains('.') + maxItems: 25 + minItems: 1 + type: array + x-kubernetes-list-type: set + nodes: + description: |- + Nodes defines a way to select a set of nodes in + the cluster. This field follows standard label selector + semantics; if present but empty, it selects all Nodes. + + + Support: Extended + + + + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + x-kubernetes-validations: + - message: networks/nodes peer cannot be set with namedPorts since + there are no namedPorts for networks/nodes + rule: '!(self.to.exists(peer, has(peer.networks) || has(peer.nodes)) + && has(self.ports) && self.ports.exists(port, has(port.namedPort)))' + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods. + A total of 100 rules will be allowed in each ANP instance. + The relative precedence of ingress rules within a single ANP object (all of + which share the priority) will be determined by the order in which the rule + is written. Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + ANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by an AdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic (even if it would otherwise have been denied by NetworkPolicy) + Deny: denies the selected traffic + Pass: instructs the selected traffic to skip any remaining ANP rules, and + then pass execution to any NetworkPolicies that select the pod. + If the pod is not selected by any NetworkPolicies then execution + is passed to any BaselineAdminNetworkPolicies that select the pod. + + + Support: Core + enum: + - Allow + - Deny + - Pass + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + Exactly one of the selector pointers must be set for a given peer. If a + consumer observes none of its fields are set, they must assume an unknown + option has been specified and fail closed. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + AdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + namedPort: + description: |- + NamedPort selects a port on a pod(s) based on name. + + + Support: Extended + + + + type: string + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + priority: + description: |- + Priority is a value from 0 to 1000. Rules with lower priority values have + higher precedence, and are checked before rules with higher priority values. + All AdminNetworkPolicy rules have higher precedence than NetworkPolicy or + BaselineAdminNetworkPolicy rules + The behavior is undefined if two ANP objects have same priority. + + + Support: Core + format: int32 + maximum: 1000 + minimum: 0 + type: integer + subject: + description: |- + Subject defines the pods to which this AdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - priority + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# Source: calico/templates/kdd-crds.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/network-policy-api/pull/30 + policy.networking.k8s.io/bundle-version: v0.1.1 + policy.networking.k8s.io/channel: experimental + creationTimestamp: null + name: baselineadminnetworkpolicies.policy.networking.k8s.io +spec: + group: policy.networking.k8s.io + names: + kind: BaselineAdminNetworkPolicy + listKind: BaselineAdminNetworkPolicyList + plural: baselineadminnetworkpolicies + shortNames: + - banp + singular: baselineadminnetworkpolicy + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + BaselineAdminNetworkPolicy is a cluster level resource that is part of the + AdminNetworkPolicy API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Specification of the desired behavior of BaselineAdminNetworkPolicy. + properties: + egress: + description: |- + Egress is the list of Egress rules to be applied to the selected pods if + they are not matched by any AdminNetworkPolicy or NetworkPolicy rules. + A total of 100 Egress rules will be allowed in each BANP instance. + The relative precedence of egress rules within a single BANP object + will be determined by the order in which the rule is written. + Thus, a rule that appears at the top of the egress rules + would take the highest precedence. + BANPs with no egress rules do not affect egress traffic. + + + Support: Core + items: + description: |- + BaselineAdminNetworkPolicyEgressRule describes an action to take on a particular + set of traffic originating from pods selected by a BaselineAdminNetworkPolicy's + Subject field. + + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic + Deny: denies the selected traffic + + + Support: Core + enum: + - Allow + - Deny + type: string + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + BaselineAdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of destination ports for the outgoing egress traffic. + If Ports is not set then the rule does not filter traffic via port. + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + namedPort: + description: |- + NamedPort selects a port on a pod(s) based on name. + + + Support: Extended + + + + type: string + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + to: + description: |- + To is the list of destinations whose traffic this rule applies to. + If any AdminNetworkPolicyEgressPeer matches the destination of outgoing + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyEgressPeer defines a peer to allow traffic to. + Exactly one of the selector pointers must be set for a given peer. If a + consumer observes none of its fields are set, they must assume an unknown + option has been specified and fail closed. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + networks: + description: |- + Networks defines a way to select peers via CIDR blocks. + This is intended for representing entities that live outside the cluster, + which can't be selected by pods, namespaces and nodes peers, but note + that cluster-internal traffic will be checked against the rule as + well. So if you Allow or Deny traffic to `"0.0.0.0/0"`, that will allow + or deny all IPv4 pod-to-pod traffic as well. If you don't want that, + add a rule that Passes all pod traffic before the Networks rule. + + + Each item in Networks should be provided in the CIDR format and should be + IPv4 or IPv6, for example "10.0.0.0/8" or "fd00::/8". + + + Networks can have upto 25 CIDRs specified. + + + Support: Extended + + + + items: + description: |- + CIDR is an IP address range in CIDR notation (for example, "10.0.0.0/8" or "fd00::/8"). + This string must be validated by implementations using net.ParseCIDR + TODO: Introduce CEL CIDR validation regex isCIDR() in Kube 1.31 when it is available. + maxLength: 43 + type: string + x-kubernetes-validations: + - message: CIDR must be either an IPv4 or IPv6 address. + IPv4 address embedded in IPv6 addresses are not + supported + rule: self.contains(':') != self.contains('.') + maxItems: 25 + minItems: 1 + type: array + x-kubernetes-list-type: set + nodes: + description: |- + Nodes defines a way to select a set of nodes in + the cluster. This field follows standard label selector + semantics; if present but empty, it selects all Nodes. + + + Support: Extended + + + + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - action + - to + type: object + x-kubernetes-validations: + - message: networks/nodes peer cannot be set with namedPorts since + there are no namedPorts for networks/nodes + rule: '!(self.to.exists(peer, has(peer.networks) || has(peer.nodes)) + && has(self.ports) && self.ports.exists(port, has(port.namedPort)))' + maxItems: 100 + type: array + ingress: + description: |- + Ingress is the list of Ingress rules to be applied to the selected pods + if they are not matched by any AdminNetworkPolicy or NetworkPolicy rules. + A total of 100 Ingress rules will be allowed in each BANP instance. + The relative precedence of ingress rules within a single BANP object + will be determined by the order in which the rule is written. + Thus, a rule that appears at the top of the ingress rules + would take the highest precedence. + BANPs with no ingress rules do not affect ingress traffic. + + + Support: Core + items: + description: |- + BaselineAdminNetworkPolicyIngressRule describes an action to take on a particular + set of traffic destined for pods selected by a BaselineAdminNetworkPolicy's + Subject field. + properties: + action: + description: |- + Action specifies the effect this rule will have on matching traffic. + Currently the following actions are supported: + Allow: allows the selected traffic + Deny: denies the selected traffic + + + Support: Core + enum: + - Allow + - Deny + type: string + from: + description: |- + From is the list of sources whose traffic this rule applies to. + If any AdminNetworkPolicyIngressPeer matches the source of incoming + traffic then the specified action is applied. + This field must be defined and contain at least one item. + + + Support: Core + items: + description: |- + AdminNetworkPolicyIngressPeer defines an in-cluster peer to allow traffic from. + Exactly one of the selector pointers must be set for a given peer. If a + consumer observes none of its fields are set, they must assume an unknown + option has been specified and fail closed. + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: |- + Namespaces defines a way to select all pods within a set of Namespaces. + Note that host-networked pods are not included in this type of peer. + + + Support: Core + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: |- + Pods defines a way to select a set of pods in + a set of namespaces. Note that host-networked pods + are not included in this type of peer. + + + Support: Core + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + maxItems: 100 + minItems: 1 + type: array + name: + description: |- + Name is an identifier for this rule, that may be no more than 100 characters + in length. This field should be used by the implementation to help + improve observability, readability and error-reporting for any applied + BaselineAdminNetworkPolicies. + + + Support: Core + maxLength: 100 + type: string + ports: + description: |- + Ports allows for matching traffic based on port and protocols. + This field is a list of ports which should be matched on + the pods selected for this policy i.e the subject of the policy. + So it matches on the destination port for the ingress traffic. + If Ports is not set then the rule does not filter traffic via port. + + + Support: Core + items: + description: |- + AdminNetworkPolicyPort describes how to select network ports on pod(s). + Exactly one field must be set. + maxProperties: 1 + minProperties: 1 + properties: + namedPort: + description: |- + NamedPort selects a port on a pod(s) based on name. + + + Support: Extended + + + + type: string + portNumber: + description: |- + Port selects a port on a pod(s) based on number. + + + Support: Core + properties: + port: + description: |- + Number defines a network port value. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + required: + - port + - protocol + type: object + portRange: + description: |- + PortRange selects a port range on a pod(s) based on provided start and end + values. + + + Support: Core + properties: + end: + description: |- + End defines a network port that is the end of a port range, the End value + must be greater than Start. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + default: TCP + description: |- + Protocol is the network protocol (TCP, UDP, or SCTP) which traffic must + match. If not specified, this field defaults to TCP. + + + Support: Core + type: string + start: + description: |- + Start defines a network port that is the start of a port range, the Start + value must be less than End. + + + Support: Core + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - end + - start + type: object + type: object + maxItems: 100 + type: array + required: + - action + - from + type: object + maxItems: 100 + type: array + subject: + description: |- + Subject defines the pods to which this BaselineAdminNetworkPolicy applies. + Note that host-networked pods are not included in subject selection. + + + Support: Core + maxProperties: 1 + minProperties: 1 + properties: + namespaces: + description: Namespaces is used to select pods via namespace selectors. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + pods: + description: Pods is used to select pods via namespace AND pod + selectors. + properties: + namespaceSelector: + description: |- + NamespaceSelector follows standard label selector semantics; if empty, + it selects all Namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + description: |- + PodSelector is used to explicitly select pods within a namespace; if empty, + it selects all Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - namespaceSelector + - podSelector + type: object + type: object + required: + - subject + type: object + status: + description: Status is the status to be reported by the implementation. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + required: + - conditions + type: object + required: + - metadata + - spec + type: object + x-kubernetes-validations: + - message: Only one baseline admin network policy with metadata.name="default" + can be created in the cluster + rule: self.metadata.name == 'default' + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +# Source: calico/templates/calico-kube-controllers-rbac.yaml +# Include a clusterrole for the kube-controllers component, +# and bind it to the calico-kube-controllers serviceaccount. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-kube-controllers +rules: + # Nodes are watched to monitor for deletions. + - apiGroups: [""] + resources: + - nodes + verbs: + - watch + - list + - get + # Pods are watched to check for existence as part of IPAM controller. + - apiGroups: [""] + resources: + - pods + verbs: + - get + - list + - watch + # Services are monitored for service LoadBalancer IP allocation + - apiGroups: [""] + resources: + - services + - services/status + verbs: + - get + - list + - update + - watch + # IPAM resources are manipulated in response to node and block updates, as well as periodic triggers. + - apiGroups: ["crd.projectcalico.org"] + resources: + - ipreservations + verbs: + - list + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + - ipamblocks + - ipamhandles + - ipamconfigs + - tiers + verbs: + - get + - list + - create + - update + - delete + - watch + # Pools are watched to maintain a mapping of blocks to IP pools. + - apiGroups: ["crd.projectcalico.org"] + resources: + - ippools + verbs: + - list + - watch + # kube-controllers manages hostendpoints. + - apiGroups: ["crd.projectcalico.org"] + resources: + - hostendpoints + verbs: + - get + - list + - create + - update + - delete + # Needs access to update clusterinformations. + - apiGroups: ["crd.projectcalico.org"] + resources: + - clusterinformations + verbs: + - get + - list + - create + - update + - watch + # KubeControllersConfiguration is where it gets its config + - apiGroups: ["crd.projectcalico.org"] + resources: + - kubecontrollersconfigurations + verbs: + # read its own config + - get + # create a default if none exists + - create + # update status + - update + # watch for changes + - watch +--- +# Source: calico/templates/calico-node-rbac.yaml +# Include a clusterrole for the calico-node DaemonSet, +# and bind it to the calico-node serviceaccount. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-node +rules: + # Used for creating service account tokens to be used by the CNI plugin + - apiGroups: [""] + resources: + - serviceaccounts/token + resourceNames: + - calico-cni-plugin + verbs: + - create + # The CNI plugin needs to get pods, nodes, and namespaces. + - apiGroups: [""] + resources: + - pods + - nodes + - namespaces + verbs: + - get + # EndpointSlices are used for Service-based network policy rule + # enforcement. + - apiGroups: ["discovery.k8s.io"] + resources: + - endpointslices + verbs: + - watch + - list + - apiGroups: [""] + resources: + - endpoints + - services + verbs: + # Used to discover service IPs for advertisement. + - watch + - list + # Used to discover Typhas. + - get + # Pod CIDR auto-detection on kubeadm needs access to config maps. + - apiGroups: [""] + resources: + - configmaps + verbs: + - get + - apiGroups: [""] + resources: + - nodes/status + verbs: + # Needed for clearing NodeNetworkUnavailable flag. + - patch + # Calico stores some configuration information in node annotations. + - update + # Watch for changes to Kubernetes NetworkPolicies. + - apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: + - watch + - list + # Watch for changes to Kubernetes (Baseline)AdminNetworkPolicies. + - apiGroups: ["policy.networking.k8s.io"] + resources: + - adminnetworkpolicies + - baselineadminnetworkpolicies + verbs: + - watch + - list + # Used by Calico for policy information. + - apiGroups: [""] + resources: + - pods + - namespaces + - serviceaccounts + verbs: + - list + - watch + # The CNI plugin patches pods/status. + - apiGroups: [""] + resources: + - pods/status + verbs: + - patch + # Calico monitors various CRDs for config. + - apiGroups: ["crd.projectcalico.org"] + resources: + - globalfelixconfigs + - felixconfigurations + - bgppeers + - bgpfilters + - globalbgpconfigs + - bgpconfigurations + - ippools + - ipreservations + - ipamblocks + - globalnetworkpolicies + - globalnetworksets + - networkpolicies + - networksets + - clusterinformations + - hostendpoints + - blockaffinities + - caliconodestatuses + - tiers + verbs: + - get + - list + - watch + # Calico creates some tiers on startup. + - apiGroups: ["crd.projectcalico.org"] + resources: + - tiers + verbs: + - create + # Calico must create and update some CRDs on startup. + - apiGroups: ["crd.projectcalico.org"] + resources: + - ippools + - felixconfigurations + - clusterinformations + verbs: + - create + - update + # Calico must update some CRDs. + - apiGroups: ["crd.projectcalico.org"] + resources: + - caliconodestatuses + verbs: + - update + # Calico stores some configuration information on the node. + - apiGroups: [""] + resources: + - nodes + verbs: + - get + - list + - watch + # These permissions are only required for upgrade from v2.6, and can + # be removed after upgrade or on fresh installations. + - apiGroups: ["crd.projectcalico.org"] + resources: + - bgpconfigurations + - bgppeers + verbs: + - create + - update + # These permissions are required for Calico CNI to perform IPAM allocations. + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + - ipamblocks + - ipamhandles + verbs: + - get + - list + - create + - update + - delete + # The CNI plugin and calico/node need to be able to create a default + # IPAMConfiguration + - apiGroups: ["crd.projectcalico.org"] + resources: + - ipamconfigs + verbs: + - get + - create + # Block affinities must also be watchable by confd for route aggregation. + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + verbs: + - watch + # The Calico IPAM migration needs to get daemonsets. These permissions can be + # removed if not upgrading from an installation using host-local IPAM. + - apiGroups: ["apps"] + resources: + - daemonsets + verbs: + - get +--- +# Source: calico/templates/calico-node-rbac.yaml +# CNI cluster role +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-cni-plugin +rules: + - apiGroups: [""] + resources: + - pods + - nodes + - namespaces + verbs: + - get + - apiGroups: [""] + resources: + - pods/status + verbs: + - patch + - apiGroups: ["crd.projectcalico.org"] + resources: + - blockaffinities + - ipamblocks + - ipamhandles + - clusterinformations + - ippools + - ipreservations + - ipamconfigs + verbs: + - get + - list + - create + - update + - delete +--- +# Source: calico/templates/calico-kube-controllers-rbac.yaml +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: calico-kube-controllers +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: calico-kube-controllers +subjects: +- kind: ServiceAccount + name: calico-kube-controllers + namespace: kube-system +--- +# Source: calico/templates/calico-node-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: calico-node +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: calico-node +subjects: +- kind: ServiceAccount + name: calico-node + namespace: kube-system +--- +# Source: calico/templates/calico-node-rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: calico-cni-plugin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: calico-cni-plugin +subjects: +- kind: ServiceAccount + name: calico-cni-plugin + namespace: kube-system +--- +# Source: calico/templates/calico-node.yaml +# This manifest installs the calico-node container, as well +# as the CNI plugins and network config on +# each master and worker node in a Kubernetes cluster. +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: calico-node + namespace: kube-system + labels: + k8s-app: calico-node +spec: + selector: + matchLabels: + k8s-app: calico-node + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + template: + metadata: + labels: + k8s-app: calico-node + spec: + nodeSelector: + kubernetes.io/os: linux + hostNetwork: true + tolerations: + # Make sure calico-node gets scheduled on all nodes. + - effect: NoSchedule + operator: Exists + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + serviceAccountName: calico-node + securityContext: + seccompProfile: + type: RuntimeDefault + # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force + # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods. + terminationGracePeriodSeconds: 0 + priorityClassName: system-node-critical + initContainers: + # This container performs upgrade from host-local IPAM to calico-ipam. + # It can be deleted if this is a fresh installation, or if you have already + # upgraded to use calico-ipam. + - name: upgrade-ipam + image: docker.io/calico/cni:master + imagePullPolicy: IfNotPresent + command: ["/opt/cni/bin/calico-ipam", "-upgrade"] + envFrom: + - configMapRef: + # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode. + name: kubernetes-services-endpoint + optional: true + env: + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: CALICO_NETWORKING_BACKEND + valueFrom: + configMapKeyRef: + name: calico-config + key: calico_backend + volumeMounts: + - mountPath: /var/lib/cni/networks + name: host-local-net-dir + - mountPath: /host/opt/cni/bin + name: cni-bin-dir + securityContext: + privileged: true + # This container installs the CNI binaries + # and CNI network config file on each node. + - name: install-cni + image: docker.io/calico/cni:master + imagePullPolicy: IfNotPresent + command: ["/opt/cni/bin/install"] + envFrom: + - configMapRef: + # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode. + name: kubernetes-services-endpoint + optional: true + env: + # Name of the CNI config file to create. + - name: CNI_CONF_NAME + value: "10-calico.conflist" + # The CNI network config to install on each node. + - name: CNI_NETWORK_CONFIG + valueFrom: + configMapKeyRef: + name: calico-config + key: cni_network_config + # Set the hostname based on the k8s node name. + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + # CNI MTU Config variable + - name: CNI_MTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # Prevents the container from sleeping forever. + - name: SLEEP + value: "false" + volumeMounts: + - mountPath: /host/opt/cni/bin + name: cni-bin-dir + - mountPath: /host/etc/cni/net.d + name: cni-net-dir + securityContext: + privileged: true + # This init container mounts the necessary filesystems needed by the BPF data plane + # i.e. bpf at /sys/fs/bpf and cgroup2 at /run/calico/cgroup. Calico-node initialisation is executed + # in best effort fashion, i.e. no failure for errors, to not disrupt pod creation in iptable mode. + - name: "mount-bpffs" + image: docker.io/calico/node:master + imagePullPolicy: IfNotPresent + command: ["calico-node", "-init", "-best-effort"] + volumeMounts: + - mountPath: /sys/fs + name: sys-fs + # Bidirectional is required to ensure that the new mount we make at /sys/fs/bpf propagates to the host + # so that it outlives the init container. + mountPropagation: Bidirectional + - mountPath: /var/run/calico + name: var-run-calico + # Bidirectional is required to ensure that the new mount we make at /run/calico/cgroup propagates to the host + # so that it outlives the init container. + mountPropagation: Bidirectional + # Mount /proc/ from host which usually is an init program at /nodeproc. It's needed by mountns binary, + # executed by calico-node, to mount root cgroup2 fs at /run/calico/cgroup to attach CTLB programs correctly. + - mountPath: /nodeproc + name: nodeproc + readOnly: true + securityContext: + privileged: true + containers: + # Runs calico-node container on each Kubernetes node. This + # container programs network policy and routes on each + # host. + - name: calico-node + image: docker.io/calico/node:master + imagePullPolicy: IfNotPresent + envFrom: + - configMapRef: + # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode. + name: kubernetes-services-endpoint + optional: true + env: + # Use Kubernetes API as the backing datastore. + - name: DATASTORE_TYPE + value: "kubernetes" + # Wait for the datastore. + - name: WAIT_FOR_DATASTORE + value: "true" + # Set based on the k8s node name. + - name: NODENAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + # Choose the backend to use. + - name: CALICO_NETWORKING_BACKEND + valueFrom: + configMapKeyRef: + name: calico-config + key: calico_backend + # Cluster type to identify the deployment type + - name: CLUSTER_TYPE + value: "k8s,bgp" + # Auto-detect the BGP IP address. + - name: IP + value: "autodetect" + # Enable IPIP + - name: CALICO_IPV4POOL_IPIP + value: "Always" + # Enable or Disable VXLAN on the default IP pool. + - name: CALICO_IPV4POOL_VXLAN + value: "Never" + # Enable or Disable VXLAN on the default IPv6 IP pool. + - name: CALICO_IPV6POOL_VXLAN + value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "IPIP" + # Set MTU for tunnel device used if ipip is enabled + - name: FELIX_IPINIPMTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # Set MTU for the VXLAN tunnel device. + - name: FELIX_VXLANMTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # Set MTU for the Wireguard tunnel device. + - name: FELIX_WIREGUARDMTU + valueFrom: + configMapKeyRef: + name: calico-config + key: veth_mtu + # The default IPv4 pool to create on startup if none exists. Pod IPs will be + # chosen from this range. Changing this value after installation will have + # no effect. This should fall within `--cluster-cidr`. + # - name: CALICO_IPV4POOL_CIDR + # value: "192.168.0.0/16" + # Disable file logging so `kubectl logs` works. + - name: CALICO_DISABLE_FILE_LOGGING + value: "true" + # Set Felix endpoint to host default action to ACCEPT. + - name: FELIX_DEFAULTENDPOINTTOHOSTACTION + value: "ACCEPT" + # Disable IPv6 on Kubernetes. + - name: FELIX_IPV6SUPPORT + value: "false" + - name: FELIX_HEALTHENABLED + value: "true" + securityContext: + privileged: true + resources: + requests: + cpu: 250m + lifecycle: + preStop: + exec: + command: + - /bin/calico-node + - -shutdown + livenessProbe: + exec: + command: + - /bin/calico-node + - -felix-live + periodSeconds: 10 + initialDelaySeconds: 10 + failureThreshold: 6 + timeoutSeconds: 10 + readinessProbe: + exec: + command: + - /bin/calico-node + - -felix-ready + periodSeconds: 10 + timeoutSeconds: 10 + volumeMounts: + # For maintaining CNI plugin API credentials. + - mountPath: /host/etc/cni/net.d + name: cni-net-dir + readOnly: false + - mountPath: /lib/modules + name: lib-modules + readOnly: true + - mountPath: /run/xtables.lock + name: xtables-lock + readOnly: false + - mountPath: /var/run/calico + name: var-run-calico + readOnly: false + - mountPath: /var/lib/calico + name: var-lib-calico + readOnly: false + - name: policysync + mountPath: /var/run/nodeagent + # For eBPF mode, we need to be able to mount the BPF filesystem at /sys/fs/bpf so we mount in the + # parent directory. + - name: bpffs + mountPath: /sys/fs/bpf + - name: cni-log-dir + mountPath: /var/log/calico/cni + readOnly: true + volumes: + # Used by calico-node. + - name: lib-modules + hostPath: + path: /lib/modules + - name: var-run-calico + hostPath: + path: /var/run/calico + type: DirectoryOrCreate + - name: var-lib-calico + hostPath: + path: /var/lib/calico + type: DirectoryOrCreate + - name: xtables-lock + hostPath: + path: /run/xtables.lock + type: FileOrCreate + - name: sys-fs + hostPath: + path: /sys/fs/ + type: DirectoryOrCreate + - name: bpffs + hostPath: + path: /sys/fs/bpf + type: Directory + # mount /proc at /nodeproc to be used by mount-bpffs initContainer to mount root cgroup2 fs. + - name: nodeproc + hostPath: + path: /proc + # Used to install CNI. + - name: cni-bin-dir + hostPath: + path: /opt/cni/bin + type: DirectoryOrCreate + - name: cni-net-dir + hostPath: + path: /etc/cni/net.d + # Used to access CNI logs. + - name: cni-log-dir + hostPath: + path: /var/log/calico/cni + # Mount in the directory for host-local IPAM allocations. This is + # used when upgrading from host-local to calico-ipam, and can be removed + # if not using the upgrade-ipam init container. + - name: host-local-net-dir + hostPath: + path: /var/lib/cni/networks + # Used to create per-pod Unix Domain Sockets + - name: policysync + hostPath: + type: DirectoryOrCreate + path: /var/run/nodeagent +--- +# Source: calico/templates/calico-kube-controllers.yaml +# See https://github.com/projectcalico/kube-controllers +apiVersion: apps/v1 +kind: Deployment +metadata: + name: calico-kube-controllers + namespace: kube-system + labels: + k8s-app: calico-kube-controllers +spec: + # The controllers can only have a single active instance. + replicas: 1 + selector: + matchLabels: + k8s-app: calico-kube-controllers + strategy: + type: Recreate + template: + metadata: + name: calico-kube-controllers + namespace: kube-system + labels: + k8s-app: calico-kube-controllers + spec: + nodeSelector: + kubernetes.io/os: linux + tolerations: + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - key: node-role.kubernetes.io/master + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + serviceAccountName: calico-kube-controllers + securityContext: + seccompProfile: + type: RuntimeDefault + priorityClassName: system-cluster-critical + containers: + - name: calico-kube-controllers + image: docker.io/calico/kube-controllers:master + imagePullPolicy: IfNotPresent + env: + # Choose which controllers to run. + - name: ENABLED_CONTROLLERS + value: node,loadbalancer + - name: DATASTORE_TYPE + value: kubernetes + livenessProbe: + exec: + command: + - /usr/bin/check-status + - -l + periodSeconds: 10 + initialDelaySeconds: 10 + failureThreshold: 6 + timeoutSeconds: 10 + readinessProbe: + exec: + command: + - /usr/bin/check-status + - -r + periodSeconds: 10 + securityContext: + runAsNonRoot: true diff --git a/manifests/calico-policy-only.yaml b/manifests/calico-policy-only.yaml index 654778662d4..fefee89f3c7 100644 --- a/manifests/calico-policy-only.yaml +++ b/manifests/calico-policy-only.yaml @@ -1984,6 +1984,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when diff --git a/manifests/calico-typha.yaml b/manifests/calico-typha.yaml index d19bbd9e040..0a4d94e404d 100644 --- a/manifests/calico-typha.yaml +++ b/manifests/calico-typha.yaml @@ -1985,6 +1985,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when @@ -7639,6 +7643,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: diff --git a/manifests/calico-vxlan.yaml b/manifests/calico-vxlan.yaml index 0073b053b1b..98b8652e836 100644 --- a/manifests/calico-vxlan.yaml +++ b/manifests/calico-vxlan.yaml @@ -1969,6 +1969,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when @@ -7597,6 +7601,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "CrossSubnet" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: diff --git a/manifests/calico.yaml b/manifests/calico.yaml index 37c321c8cf2..522fb3dbf63 100644 --- a/manifests/calico.yaml +++ b/manifests/calico.yaml @@ -1969,6 +1969,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when @@ -7597,6 +7601,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: diff --git a/manifests/canal.yaml b/manifests/canal.yaml index a82b28883fc..e12c1c7da7e 100644 --- a/manifests/canal.yaml +++ b/manifests/canal.yaml @@ -1986,6 +1986,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when diff --git a/manifests/crds.yaml b/manifests/crds.yaml index 17b408e1bc7..d844d6089ef 100644 --- a/manifests/crds.yaml +++ b/manifests/crds.yaml @@ -1879,6 +1879,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when diff --git a/manifests/flannel-migration/calico.yaml b/manifests/flannel-migration/calico.yaml index e39c4e6066e..384d6a5da56 100644 --- a/manifests/flannel-migration/calico.yaml +++ b/manifests/flannel-migration/calico.yaml @@ -1969,6 +1969,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when @@ -7599,6 +7603,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: diff --git a/manifests/ocp/crd.projectcalico.org_felixconfigurations.yaml b/manifests/ocp/crd.projectcalico.org_felixconfigurations.yaml index f74fdc717b8..008c761bc5a 100644 --- a/manifests/ocp/crd.projectcalico.org_felixconfigurations.yaml +++ b/manifests/ocp/crd.projectcalico.org_felixconfigurations.yaml @@ -865,6 +865,10 @@ spec: policy changes to external services, like Application layer policy. [Default: Empty]' type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: 'PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when set diff --git a/manifests/operator-crds.yaml b/manifests/operator-crds.yaml index 684a1fac7a7..7c63ae4f150 100644 --- a/manifests/operator-crds.yaml +++ b/manifests/operator-crds.yaml @@ -20505,6 +20505,10 @@ spec: PolicySyncPathPrefix is used to by Felix to communicate policy changes to external services, like Application layer policy. [Default: Empty] type: string + programRoutes: + description: 'ProgramRoutes specifies what type of routes Felix should + program. [Default: None]. [Default: None]' + type: string prometheusGoMetricsEnabled: description: |- PrometheusGoMetricsEnabled disables Go runtime metrics collection, which the Prometheus client does by default, when diff --git a/node/filesystem/etc/rc.local b/node/filesystem/etc/rc.local index 24768f9dff2..8efbdf9f46a 100755 --- a/node/filesystem/etc/rc.local +++ b/node/filesystem/etc/rc.local @@ -52,6 +52,10 @@ case "$CALICO_NETWORKING_BACKEND" in # If running in policy only mode, we don't need to run BIRD / Confd. echo "CALICO_NETWORKING_BACKEND is none - no BGP daemon running" ;; + "ipip" ) + # If running in IPIP-only mode, we don't need to run BIRD / Confd. + echo "CALICO_NETWORKING_BACKEND is ipip - no need to run a BGP daemon" + ;; "vxlan" ) # If running in VXLAN-only mode, we don't need to run BIRD / Confd. echo "CALICO_NETWORKING_BACKEND is vxlan - no need to run a BGP daemon" diff --git a/node/tests/k8st/infra/calico-kdd.yaml b/node/tests/k8st/infra/calico-kdd.yaml index ad1f5883dce..80afc69ede3 100644 --- a/node/tests/k8st/infra/calico-kdd.yaml +++ b/node/tests/k8st/infra/calico-kdd.yaml @@ -673,6 +673,9 @@ spec: # Enable or Disable VXLAN on the default IPv6 IP pool. - name: CALICO_IPV6POOL_VXLAN value: "Never" + # Set if Felix should program IPIP routes or not. + - name: FELIX_PROGRAMROUTES + value: "None" # Set MTU for tunnel device used if ipip is enabled - name: FELIX_IPINIPMTU valueFrom: