k3s-io / kube-router Goto Github PK
View Code? Open in Web Editor NEWThis project forked from cloudnativelabs/kube-router
Kube-router, a turnkey solution for Kubernetes networking.
Home Page: https://kube-router.io
License: Apache License 2.0
This project forked from cloudnativelabs/kube-router
Kube-router, a turnkey solution for Kubernetes networking.
Home Page: https://kube-router.io
License: Apache License 2.0
In pkg/controllers/netpol/policy.go you have the variable currnetPodIps but I guess you mean currentPodIps ;)
This code was removed from line 131 of pkg/controllers/netpol/policy.go:
err := ipset.Restore()
if err != nil {
return nil, nil, fmt.Errorf("failed to perform ipset restore: %s", err.Error())
}
That means, inside the for ipFamily, ipset := range npc.ipSetHandlers { loop but outside the for _, policy := range networkPoliciesInfo { loop
Without this code, the ipsets are not created and iptables complains
ipv4 ipsets require family inet
and ipv6 ipsets require family inet6
. Therefore, we need to create different ipsets for each type of addresses.
For example, in function syncNetworkPolicyChains
of pkg/controllers/netpol/policy.go
we should do something like this for the ingress part of the policy:
// ensure there is a unique chain per network policy in filter table
policyChainName := networkPolicyChainName(policy.namespace, policy.name, version, ipFamily)
npc.filterTableRules[ipFamily].WriteString(":" + policyChainName + "\n")
activePolicyChains[policyChainName] = true
var currentPodIps []api.PodIP
for _, pod := range policy.targetPods {
for _, ip := range pod.ips {
currentPodIps = append(currentPodIps, ip)
}
}
if policy.policyType == "both" || policy.policyType == "ingress" {
// create a ipset for all destination pod ip's matched by the policy spec PodSelector
targetDestPodIPSetName := policyDestinationPodIPSetName(policy.namespace, policy.name, ipFamily)
setEntries := make([][]string, 0)
for _, podIP := range currentPodIps {
if ipFamily == api.IPv4Protocol {
if utilsnet.IsIPv4String(podIP.IP) {
setEntries = append(setEntries, []string{podIP.IP, utils.OptionTimeout, "0"})
}
}
if ipFamily == api.IPv6Protocol {
if utilsnet.IsIPv6String(podIP.IP) {
setEntries = append(setEntries, []string{podIP.IP, utils.OptionTimeout, "0", "family", "inet6"})
}
}
}
ipset.RefreshSet(targetDestPodIPSetName, setEntries, utils.TypeHashIP)
if err := npc.processIngressRules(policy, targetDestPodIPSetName, activePolicyIPSets, version, ipFamily); err != nil {
return nil, nil, err
}
activePolicyIPSets[targetDestPodIPSetName] = true
}
In other words, loop over the currenPodIps and verify if they are ipv4 or ipv6. And if we are in the matching ipset handler IPFamily, create an ipset with the special option for ipv6 "family", "inet6"
.
This should be executed in several places where we call the RefreshSet
Creating ipBlock of type ipv4 or ipv6 does not work because it tries to create an ipset of both ip address.
When creating an ipBlock with an ipv4 range, the error is:
Aborting sync. Failed to sync network policy chains: failed to perform ipset restore: ipset v7.6: Error in line 9: Syntax error: cannot parse 10.42.0.8: resolving to IPv6 address failed
When creating an ipBlock of an ipv6 range (/126), the error is:
Aborting sync. Failed to sync network policy chains: failed to perform ipset restore: ipset v7.6: Error in line 10: Syntax error: '126' is out of range 0-32
In "pkg/controllers/netpol/policy.go" you have this loop:
for ip := range policy.targetPods {
if utilsnet.IsIPv4String(ip) {
currnetPodIps[v1core.IPv4Protocol] = append(currnetPodIps[v1core.IPv4Protocol], ip)
}
if utilsnet.IsIPv6String(ip) {
currnetPodIps[v1core.IPv6Protocol] = append(currnetPodIps[v1core.IPv6Protocol], ip)
}
}
However, policy.targetPods is a map, e.g. map[10.42.0.11:{[{10.42.0.11} {2001:cafe:42::b}]. Therefore, ip is always the ipv4 address (in the example 10.42.0.11) becuase it is the key of the map. We should do for _, pod := range policy.targetPods
Then, we get podInfo structs:
type podInfo struct {
ips []v1core.PodIP
name string
namespace string
labels map[string]string
}
So we need an extra loop for the ips field. And then, we should use the IP field to get the string value. In summary:
currnetPodIps := make(map[v1core.IPFamily][]string)
for _, pod := range policy.targetPods {
for _, ip := range pod.ips {
if utilsnet.IsIPv4String(ip.IP) {
currnetPodIps[v1core.IPv4Protocol] = append(currnetPodIps[v1core.IPv4Protocol], ip.IP)
}
if utilsnet.IsIPv6String(ip.IP) {
currnetPodIps[v1core.IPv6Protocol] = append(currnetPodIps[v1core.IPv6Protocol], ip.IP)
}
}
}
ipv4 ipsets require family inet
and ipv6 ipsets require family inet6
Therefore, we need to create different ipsets for each type of address. To do so, the SHA that is part of the ipset name needs to be different and thus, we should include the ipFamily to it.
At the end of pkg/controllers/netpol/policy.go
, we should add the ipFamily parameter to the SHA calculation to the first three functions:
func networkPolicyChainName(namespace, policyName string, version string, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + version + string(ipFamily)))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeNetworkPolicyChainPrefix + encoded[:16]
}
func policySourcePodIPSetName(namespace, policyName string, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + string(ipFamily)))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeSourceIPSetPrefix + encoded[:16]
}
func policyDestinationPodIPSetName(namespace, policyName string, ipFamily api.IPFamily) string {
hash := sha256.Sum256([]byte(namespace + policyName + string(ipFamily)))
encoded := base32.StdEncoding.EncodeToString(hash[:])
return kubeDestinationIPSetPrefix + encoded[:16]
Of course, the places where we are calling these functions must be changed to include ipFamily (it's pretty easy as all calls to those functions have access to ipFamily)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.