rootlessnetns: cache dns and guest addr options
When using the rootless netns (bridge mode) so far podman ignored the proper pasta or slirp4netns dns sever for networks without aardvark-dns. This is not good. We should try to use them by default, and with the new MapGuestAddr option we need to use that as well for host.containers.internal. The problem is that becuase we only know what options we uses when we started the process later container starts from a new podman process do not really see these options if we just cache the result in memory. So in order to make all following podman process aware we serialize this info struct as json and later processes read it when needed. It also means we do not have to lookup the netns ip evey time so I removed that code. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
parent
a3c9f2bd9d
commit
74553777c6
|
|
@ -1,6 +1,7 @@
|
||||||
package rootlessnetns
|
package rootlessnetns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
|
@ -34,6 +35,9 @@ const (
|
||||||
// refCountFile file name for the ref count file
|
// refCountFile file name for the ref count file
|
||||||
refCountFile = "ref-count"
|
refCountFile = "ref-count"
|
||||||
|
|
||||||
|
// infoCacheFile file name for the cache file used to store the rootless netns info
|
||||||
|
infoCacheFile = "info.json"
|
||||||
|
|
||||||
// rootlessNetNsConnPidFile is the name of the rootless netns slirp4netns/pasta pid file
|
// rootlessNetNsConnPidFile is the name of the rootless netns slirp4netns/pasta pid file
|
||||||
rootlessNetNsConnPidFile = "rootless-netns-conn.pid"
|
rootlessNetNsConnPidFile = "rootless-netns-conn.pid"
|
||||||
|
|
||||||
|
|
@ -54,11 +58,9 @@ type Netns struct {
|
||||||
// config contains containers.conf options.
|
// config contains containers.conf options.
|
||||||
config *config.Config
|
config *config.Config
|
||||||
|
|
||||||
// ipAddresses used in the netns, this is needed to store
|
// info contain information about ip addresses used in the netns.
|
||||||
// the netns ips that are used by pasta. This is then handed
|
// A caller can get this info via Info().
|
||||||
// back to the caller via IPAddresses() which then can make
|
info *types.RootlessNetnsInfo
|
||||||
// sure to not use them for host.containers.internal.
|
|
||||||
ipAddresses []net.IP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type rootlessNetnsError struct {
|
type rootlessNetnsError struct {
|
||||||
|
|
@ -115,6 +117,9 @@ func (n *Netns) getOrCreateNetns() (ns.NetNS, bool, error) {
|
||||||
// quick check if pasta/slirp4netns are still running
|
// quick check if pasta/slirp4netns are still running
|
||||||
err := unix.Kill(pid, 0)
|
err := unix.Kill(pid, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if err := n.deserializeInfo(); err != nil {
|
||||||
|
return nil, false, wrapError("deserialize info", err)
|
||||||
|
}
|
||||||
// All good, return the netns.
|
// All good, return the netns.
|
||||||
return nsRef, false, nil
|
return nsRef, false, nil
|
||||||
}
|
}
|
||||||
|
|
@ -227,6 +232,15 @@ func (n *Netns) setupPasta(nsPath string) error {
|
||||||
return wrapError("create resolv.conf", err)
|
return wrapError("create resolv.conf", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.info = &types.RootlessNetnsInfo{
|
||||||
|
IPAddresses: res.IPAddresses,
|
||||||
|
DnsForwardIps: res.DNSForwardIPs,
|
||||||
|
MapGuestIps: res.MapGuestAddrIPs,
|
||||||
|
}
|
||||||
|
if err := n.serializeInfo(); err != nil {
|
||||||
|
return wrapError("serialize info", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,6 +275,12 @@ func (n *Netns) setupSlirp4netns(nsPath string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapError("determine default slirp4netns DNS address", err)
|
return wrapError("determine default slirp4netns DNS address", err)
|
||||||
}
|
}
|
||||||
|
nameservers := []string{resolveIP.String()}
|
||||||
|
|
||||||
|
netnsIP, err := slirp4netns.GetIP(res.Subnet)
|
||||||
|
if err != nil {
|
||||||
|
return wrapError("determine default slirp4netns ip address", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := resolvconf.New(&resolvconf.Params{
|
if err := resolvconf.New(&resolvconf.Params{
|
||||||
Path: n.getPath(resolvConfName),
|
Path: n.getPath(resolvConfName),
|
||||||
|
|
@ -270,10 +290,19 @@ func (n *Netns) setupSlirp4netns(nsPath string) error {
|
||||||
},
|
},
|
||||||
IPv6Enabled: res.IPv6,
|
IPv6Enabled: res.IPv6,
|
||||||
KeepHostServers: true,
|
KeepHostServers: true,
|
||||||
Nameservers: []string{resolveIP.String()},
|
Nameservers: nameservers,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return wrapError("create resolv.conf", err)
|
return wrapError("create resolv.conf", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.info = &types.RootlessNetnsInfo{
|
||||||
|
IPAddresses: []net.IP{*netnsIP},
|
||||||
|
DnsForwardIps: nameservers,
|
||||||
|
}
|
||||||
|
if err := n.serializeInfo(); err != nil {
|
||||||
|
return wrapError("serialize info", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,20 +570,6 @@ func (n *Netns) runInner(toRun func() error, cleanup bool) (err error) {
|
||||||
if err := toRun(); err != nil {
|
if err := toRun(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the current active addresses in the netns, and store them
|
|
||||||
addrs, err := net.InterfaceAddrs()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ips := make([]net.IP, 0, len(addrs))
|
|
||||||
for _, addr := range addrs {
|
|
||||||
// make sure to skip localhost and other special addresses
|
|
||||||
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() {
|
|
||||||
ips = append(ips, ipnet.IP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n.ipAddresses = ips
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -630,9 +645,7 @@ func (n *Netns) Run(lock *lockfile.LockFile, toRun func() error) error {
|
||||||
// IPAddresses returns the currently used ip addresses in the netns
|
// IPAddresses returns the currently used ip addresses in the netns
|
||||||
// These should then not be assigned for the host.containers.internal entry.
|
// These should then not be assigned for the host.containers.internal entry.
|
||||||
func (n *Netns) Info() *types.RootlessNetnsInfo {
|
func (n *Netns) Info() *types.RootlessNetnsInfo {
|
||||||
return &types.RootlessNetnsInfo{
|
return n.info
|
||||||
IPAddresses: n.ipAddresses,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func refCount(dir string, inc int) (int, error) {
|
func refCount(dir string, inc int) (int, error) {
|
||||||
|
|
@ -671,3 +684,26 @@ func readPidFile(path string) (int, error) {
|
||||||
}
|
}
|
||||||
return strconv.Atoi(strings.TrimSpace(string(b)))
|
return strconv.Atoi(strings.TrimSpace(string(b)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Netns) serializeInfo() error {
|
||||||
|
f, err := os.Create(filepath.Join(n.dir, infoCacheFile))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return json.NewEncoder(f).Encode(n.info)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Netns) deserializeInfo() error {
|
||||||
|
f, err := os.Open(filepath.Join(n.dir, infoCacheFile))
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if n.info == nil {
|
||||||
|
n.info = new(types.RootlessNetnsInfo)
|
||||||
|
}
|
||||||
|
return json.NewDecoder(f).Decode(n.info)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,10 @@ type TeardownOptions struct {
|
||||||
type RootlessNetnsInfo struct {
|
type RootlessNetnsInfo struct {
|
||||||
// IPAddresses used in the netns, must not be used for host.containers.internal
|
// IPAddresses used in the netns, must not be used for host.containers.internal
|
||||||
IPAddresses []net.IP
|
IPAddresses []net.IP
|
||||||
|
// DnsForwardIps ips used in resolv.conf
|
||||||
|
DnsForwardIps []string
|
||||||
|
// MapGuestIps should be used for the host.containers.internal entry when set
|
||||||
|
MapGuestIps []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterFunc can be passed to NetworkList to filter the networks.
|
// FilterFunc can be passed to NetworkList to filter the networks.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue