Skip to content

Commit 505d444

Browse files
samuelkarpthaJeztah
authored andcommitted
cri: write generated CNI config atomically on Unix
The 10-containerd-net.conflist file generated from the conf_template should be written atomically so that partial writes are not visible to CNI plugins. Use the new consistentfile package to ensure this on Unix-like platforms such as Linux, FreeBSD, and Darwin. Fixes #8607 Signed-off-by: Samuel Karp <[email protected]> (cherry picked from commit 3c4a1ab) Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent b2d2d38 commit 505d444

1 file changed

Lines changed: 30 additions & 22 deletions

File tree

pkg/cri/server/update_runtime_config.go

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ import (
2525
"text/template"
2626
"time"
2727

28-
"github.com/containerd/containerd/log"
2928
"golang.org/x/net/context"
3029
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
30+
31+
"github.com/containerd/containerd/log"
32+
"github.com/containerd/containerd/pkg/atomicfile"
3133
)
3234

3335
// cniConfigTemplate contains the values containerd will overwrite
@@ -89,27 +91,8 @@ func (c *criService) UpdateRuntimeConfig(ctx context.Context, r *runtime.UpdateR
8991
log.G(ctx).Infof("CNI config is successfully loaded, skip generating cni config from template %q", confTemplate)
9092
return &runtime.UpdateRuntimeConfigResponse{}, nil
9193
}
92-
log.G(ctx).Infof("Generating cni config from template %q", confTemplate)
93-
// generate cni config file from the template with updated pod cidr.
94-
t, err := template.ParseFiles(confTemplate)
95-
if err != nil {
96-
return nil, fmt.Errorf("failed to parse cni config template %q: %w", confTemplate, err)
97-
}
98-
if err := os.MkdirAll(c.config.NetworkPluginConfDir, 0755); err != nil {
99-
return nil, fmt.Errorf("failed to create cni config directory: %q: %w", c.config.NetworkPluginConfDir, err)
100-
}
101-
confFile := filepath.Join(c.config.NetworkPluginConfDir, cniConfigFileName)
102-
f, err := os.OpenFile(confFile, os.O_WRONLY|os.O_CREATE, 0644)
103-
if err != nil {
104-
return nil, fmt.Errorf("failed to open cni config file %q: %w", confFile, err)
105-
}
106-
defer f.Close()
107-
if err := t.Execute(f, cniConfigTemplate{
108-
PodCIDR: cidrs[0],
109-
PodCIDRRanges: cidrs,
110-
Routes: routes,
111-
}); err != nil {
112-
return nil, fmt.Errorf("failed to generate cni config file %q: %w", confFile, err)
94+
if err := writeCNIConfigFile(ctx, c.config.NetworkPluginConfDir, confTemplate, cidrs[0], cidrs, routes); err != nil {
95+
return nil, err
11396
}
11497
return &runtime.UpdateRuntimeConfigResponse{}, nil
11598
}
@@ -139,3 +122,28 @@ func getRoutes(cidrs []string) ([]string, error) {
139122
}
140123
return routes, nil
141124
}
125+
126+
func writeCNIConfigFile(ctx context.Context, confDir string, confTemplate string, podCIDR string, podCIDRRanges []string, routes []string) error {
127+
log.G(ctx).Infof("Generating cni config from template %q", confTemplate)
128+
// generate cni config file from the template with updated pod cidr.
129+
t, err := template.ParseFiles(confTemplate)
130+
if err != nil {
131+
return fmt.Errorf("failed to parse cni config template %q: %w", confTemplate, err)
132+
}
133+
if err := os.MkdirAll(confDir, 0755); err != nil {
134+
return fmt.Errorf("failed to create cni config directory: %q: %w", confDir, err)
135+
}
136+
confFile := filepath.Join(confDir, cniConfigFileName)
137+
f, err := atomicfile.New(confFile, 0o644)
138+
defer func() {
139+
err = f.Close()
140+
}()
141+
if err := t.Execute(f, cniConfigTemplate{
142+
PodCIDR: podCIDR,
143+
PodCIDRRanges: podCIDRRanges,
144+
Routes: routes,
145+
}); err != nil {
146+
return fmt.Errorf("failed to generate cni config file %q: %w", confFile, err)
147+
}
148+
return err
149+
}

0 commit comments

Comments
 (0)