-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs for network light #2397
docs for network light #2397
Conversation
Signed-off-by: Ashraf Fouda <[email protected]>
Signed-off-by: Ashraf Fouda <[email protected]>
Signed-off-by: Ashraf Fouda <[email protected]>
Signed-off-by: Ashraf Fouda <[email protected]>
Signed-off-by: Ashraf Fouda <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't cover all the PR because of its size. But i think I have left enough comments for the first iteration.
I think using the Light
prefix might not be the best approach. Maybe use a version instead? so it's future proof
bootstrap/bootstrap/src/config.rs
Outdated
.arg( | ||
Arg::with_name("light") | ||
.short("l") | ||
.takes_value(false) | ||
.help("run in light mode, will use the bootstrap:development.flist"), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The light flag same as the runmode should be parsed from the kernel cmdline arguments not from the bootstrap command arguments.
cmds/modules/netlightd/nft.go
Outdated
@@ -16,6 +16,7 @@ func ensureHostFw(ctx context.Context) error { | |||
nft 'add table inet filter' | |||
nft 'add table arp filter' | |||
nft 'add table bridge filter' | |||
nft 'add table nat' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really think this entire file can completely replaced now with a .nft
file basically rewrite this as a ruleset (similar to what we have under nft/rules.nft)
It's way cleaner than executing individual commands
|
||
// getVmMetrics will collect network consumption every 5 min and store | ||
// it in the rrd database. | ||
func (r *Reporter) getGwMetrics(ctx context.Context, slot rrd.Slot) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will probably be re-added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we decided to postpone gw and qsfs for later versions of zos light
etc/zinit/networkd.yaml
Outdated
test: zbusdebug --module network | ||
exec: netlightd --broker unix:///var/run/redis.sock --root /var/cache/modules/networkd | ||
|
||
# test: zbusdebug --module network |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still have to have something here to let other modules know that this networking is ready. I am sure netlightd also has a "zbus" service which means we can use the same test command but with different module name (if the module name was changed even)
pkg/environment/environment.go
Outdated
@@ -321,6 +321,10 @@ func getEnvironmentFromParams(params kernel.Params) (Environment, error) { | |||
if e := os.Getenv("ZOS_BIN_REPO"); e != "" { | |||
env.BinRepo = e | |||
} | |||
env.Light = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This of course is not needed, since the zero value for bool in Go is false.
pkg/gridtypes/zos/types.go
Outdated
// NetworkLightType type | ||
NetworkLightType gridtypes.WorkloadType = "network-light" | ||
// ZDBLightType type | ||
ZDBLightType gridtypes.WorkloadType = "zdb-light" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need zdb-light? is it because it doesn't have ygg IP?
I think we should only use the "-light" suffix if the data type for input or output changes (like vm and network) but I don't believe this applies to zdb
} | ||
|
||
// myceliumIpSeed is 6 bytes | ||
func (r *Resource) AttachPrivate(id string, vmIp net.IP) (device pkg.TapDevice, err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't figure out if this an idempotent function or not. But it's usually important that such functions to be idempotent so recreation doesn't happen if the service was restarted for example
pkg/network_light.go
Outdated
Name string | ||
Mac net.HardwareAddr | ||
IP *net.IPNet | ||
Gateway *net.IPNet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be Routes
instead so we can also have custom routes not only default GW. It's needed with mycelium for example and in other cases where custom routing is required
rename zdblight to zdb and do some hardening Signed-off-by: Ashraf Fouda <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ashraffouda for the great work. I still have few comments in case you are interested
@@ -26,15 +26,19 @@ fn bootstrap_zos(cfg: &config::Config) -> Result<()> { | |||
let flist = match &cfg.runmode { | |||
RunMode::Prod => match &cfg.version { | |||
Version::V3 => "zos:production-3:latest.flist", | |||
_ => bail!("unsupported version in old style"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's safe to completely remove the old style from code since ALL environments have been updated to new style. We needed to keep the old style for a while because bootstrap is shared between all environments (since it's part of base image) because some envs used new style and others didn't.
Anyway, you can assume that old style does no longer exist
if err := nft.Apply(rules, ""); err != nil { | ||
return fmt.Errorf("failed to apply host nft rules: %w", err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
close the rules
file here
@@ -0,0 +1,29 @@ | |||
add table inet filter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant with this is to make it similar to other rules.nft
(in the same PR here style. It doesn't have commands but instead the complete structure of the rule set
It contains simply the output of running nft list ruleset
If you don't get what I mean let me explain over DM
if err := nft.Apply(rules, nsName); err != nil { | ||
return nil, fmt.Errorf("failed to apply nft rules for namespace '%s': %w", name, err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
close rules file here
Name string | ||
Mac net.HardwareAddr | ||
IP *net.IPNet | ||
Routes []Route |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is Route defined
envName := mode.String() | ||
if u.boot.Version().Major == 4 { | ||
envName = fmt.Sprintf("%s-light", envName) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a fork and the entire fork knows that this is version 4. Hence you can always assume the envName to be "-light" without even the need to check for the major version
@@ -24,43 +23,6 @@ const ( | |||
cloudConsoleBin = "cloud-console" | |||
) | |||
|
|||
// startCloudConsole Starts the cloud console for the vm on it's private network ip | |||
func (m *Machine) startCloudConsole(ctx context.Context, namespace string, networkAddr net.IPNet, machineIP net.IPNet, ptyPath string, logs string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the cloud console can stay since the user network will always have a mycelium IP. the console can still work over the mycelium IP in case the VM is not reachable for any reason.
- So the ip of the vm is the VM private ip (private range)
- The console listen port is calculated the same way
- The console IP itself is the mycelium IP assigned to this user mycelium instance.
@@ -131,12 +93,16 @@ func (m *Machine) Run(ctx context.Context, socket, logs string) (pkg.MachineInfo | |||
|
|||
for _, nic := range m.Interfaces { | |||
var typ InterfaceType | |||
typ, _, err = nic.getType() | |||
typ, idx, err := nic.getType() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you do Attach on the resource, you should create a tap device (not macvtap) which makes it easier to attach it to CH command line. The macvtap case was only used for public IPs specifically.
} | ||
_, getLinkErr := netlink.LinkByName(tapName) | ||
if getLinkErr != nil { | ||
mtap, err := macvtap.CreateMACvTap(tapName, privateNetBr, hw) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We create TAP devices for VMs not Macvtap. this makes it un0necessary complex to pass this device to the VM when it can just be a tap device
myBr := fmt.Sprintf("m%s", r.name) | ||
hw := ifaceutil.HardwareAddrFromInputBytes([]byte(tapName)) | ||
|
||
_, err = macvtap.CreateMACvTap(tapName, myBr, hw) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for mycelium this can perfectly be a tap device (not macvtap) hence it becomes simpler to pass to the cloud-hypervisor
command line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
macvtaps or macvlans are a disaster if they're more than one with a bridge interface as parent.
Somewhere since that dummy necessity version, macvlans have problems ... what they specifically are, I'm not sure yet, but I suspect seen that macvlans are also bridges in a lighter version, they don't cooperate well with regular bridges
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I felt like since the https://bugzilla.kernel.org/show_bug.cgi?id=214631 bug, macvlans went worse and worse over time.
probably because of their infrequent use.
let's see how much work it is, but I guess
@@ -199,42 +187,14 @@ func (p *Manager) virtualMachineProvisionImpl(ctx context.Context, wl *gridtypes | |||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we only have/use one private network, why still looping all net interfaces instead of using the only used one?
networkInfo.Ifaces = append(networkInfo.Ifaces, inf) | ||
result.PlanetaryIP = inf.IPs[0].IP.String() | ||
} | ||
|
||
if config.Network.Mycelium != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it allowed to not have mycelium?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not allowed according to the specs, CMIIW
|
||
var _ pkg.NetworkerLight = (*networker)(nil) | ||
|
||
func NewNetworker() (pkg.NetworkerLight, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it common to add er
to the struct
in zos
?
because er
suffix usually used for interface
, not struct
var addrs []netlink.Addr | ||
|
||
if err = netNs.Do(func(_ ns.NetNS) error { | ||
link, err := netlink.LinkByName(infPrivate) | ||
if err != nil { | ||
return err | ||
} | ||
addrs, err = netlink.AddrList(link, netlink.FAMILY_V4) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}); err != nil { | ||
return | ||
} | ||
if len(addrs) != 1 { | ||
return device, fmt.Errorf("expect addresses on private interface to be 1 got %d", len(addrs)) | ||
} | ||
gw := addrs[0].IPNet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for readability, i think we can move this block into separate func, maybe something like:
getAndValidateAddr()
And maybe including the code to get the namespace
nsName := fmt.Sprintf("n%s", r.name)
netNs, err := namespace.GetByName(nsName)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think the code below it can also be included
if !gw.Contains(vmIp) {
return device, fmt.Errorf("ip not in range")
}
Mask: gw.Mask, | ||
} | ||
_, getLinkErr := netlink.LinkByName(tapName) | ||
if getLinkErr != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, is it OK if the tap
already exists?
} | ||
|
||
func inspectMycelium(seed []byte) (inspection MyceliumInspection, err error) { | ||
// we check if the file exists before we do inspect because mycelium will create a random seed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we check if the file exists
can't find the check
return inspection, fmt.Errorf("failed to write seed: %w", err) | ||
} | ||
|
||
tmp.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to the above of the if
block?
ايش منتظرين طال عمرك |
this pr is merged in zos4 long time ago will close it |
Signed-off-by: Ashraf Fouda [email protected]### Description
Describe the changes introduced by this PR and what does it affect
Changes
List of changes this PR includes
Related Issues
List of related issues
Checklist