1/* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15*/ 16 17package config 18 19import ( 20 "context" 21 "net/url" 22 "time" 23 24 "github.com/BurntSushi/toml" 25 "github.com/containerd/containerd/log" 26 "github.com/containerd/containerd/plugin" 27 "github.com/pkg/errors" 28) 29 30// Runtime struct to contain the type(ID), engine, and root variables for a default runtime 31// and a runtime for untrusted worload. 32type Runtime struct { 33 // Type is the runtime type to use in containerd e.g. io.containerd.runtime.v1.linux 34 Type string `toml:"runtime_type" json:"runtimeType"` 35 // Engine is the name of the runtime engine used by containerd. 36 // This only works for runtime type "io.containerd.runtime.v1.linux". 37 // DEPRECATED: use Options instead. Remove when shim v1 is deprecated. 38 Engine string `toml:"runtime_engine" json:"runtimeEngine"` 39 // PodAnnotations is a list of pod annotations passed to both pod sandbox as well as 40 // container OCI annotations. 41 PodAnnotations []string `toml:"pod_annotations" json:"PodAnnotations"` 42 // ContainerAnnotations is a list of container annotations passed through to the OCI config of the containers. 43 // Container annotations in CRI are usually generated by other Kubernetes node components (i.e., not users). 44 // Currently, only device plugins populate the annotations. 45 ContainerAnnotations []string `toml:"container_annotations" json:"ContainerAnnotations"` 46 // Root is the directory used by containerd for runtime state. 47 // DEPRECATED: use Options instead. Remove when shim v1 is deprecated. 48 // This only works for runtime type "io.containerd.runtime.v1.linux". 49 Root string `toml:"runtime_root" json:"runtimeRoot"` 50 // Options are config options for the runtime. If options is loaded 51 // from toml config, it will be toml.Primitive. 52 Options *toml.Primitive `toml:"options" json:"options"` 53 // PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the 54 // runtime spec when the container is privileged. Defaults to false. 55 PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices" json:"privileged_without_host_devices"` 56 // BaseRuntimeSpec is a json file with OCI spec to use as base spec that all container's will be created from. 57 BaseRuntimeSpec string `toml:"base_runtime_spec" json:"baseRuntimeSpec"` 58} 59 60// ContainerdConfig contains toml config related to containerd 61type ContainerdConfig struct { 62 // Snapshotter is the snapshotter used by containerd. 63 Snapshotter string `toml:"snapshotter" json:"snapshotter"` 64 // DefaultRuntimeName is the default runtime name to use from the runtimes table. 65 DefaultRuntimeName string `toml:"default_runtime_name" json:"defaultRuntimeName"` 66 // DefaultRuntime is the default runtime to use in containerd. 67 // This runtime is used when no runtime handler (or the empty string) is provided. 68 // DEPRECATED: use DefaultRuntimeName instead. Remove in containerd 1.4. 69 DefaultRuntime Runtime `toml:"default_runtime" json:"defaultRuntime"` 70 // UntrustedWorkloadRuntime is a runtime to run untrusted workloads on it. 71 // DEPRECATED: use `untrusted` runtime in Runtimes instead. Remove in containerd 1.4. 72 UntrustedWorkloadRuntime Runtime `toml:"untrusted_workload_runtime" json:"untrustedWorkloadRuntime"` 73 // Runtimes is a map from CRI RuntimeHandler strings, which specify types of runtime 74 // configurations, to the matching configurations. 75 Runtimes map[string]Runtime `toml:"runtimes" json:"runtimes"` 76 // NoPivot disables pivot-root (linux only), required when running a container in a RamDisk with runc 77 // This only works for runtime type "io.containerd.runtime.v1.linux". 78 NoPivot bool `toml:"no_pivot" json:"noPivot"` 79 80 // DisableSnapshotAnnotations disables to pass additional annotations (image 81 // related information) to snapshotters. These annotations are required by 82 // stargz snapshotter (https://github.com/containerd/stargz-snapshotter). 83 DisableSnapshotAnnotations bool `toml:"disable_snapshot_annotations" json:"disableSnapshotAnnotations"` 84 85 // DiscardUnpackedLayers is a boolean flag to specify whether to allow GC to 86 // remove layers from the content store after successfully unpacking these 87 // layers to the snapshotter. 88 DiscardUnpackedLayers bool `toml:"discard_unpacked_layers" json:"discardUnpackedLayers"` 89} 90 91// CniConfig contains toml config related to cni 92type CniConfig struct { 93 // NetworkPluginBinDir is the directory in which the binaries for the plugin is kept. 94 NetworkPluginBinDir string `toml:"bin_dir" json:"binDir"` 95 // NetworkPluginConfDir is the directory in which the admin places a CNI conf. 96 NetworkPluginConfDir string `toml:"conf_dir" json:"confDir"` 97 // NetworkPluginMaxConfNum is the max number of plugin config files that will 98 // be loaded from the cni config directory by go-cni. Set the value to 0 to 99 // load all config files (no arbitrary limit). The legacy default value is 1. 100 NetworkPluginMaxConfNum int `toml:"max_conf_num" json:"maxConfNum"` 101 // NetworkPluginConfTemplate is the file path of golang template used to generate 102 // cni config. 103 // When it is set, containerd will get cidr(s) from kubelet to replace {{.PodCIDR}}, 104 // {{.PodCIDRRanges}} or {{.Routes}} in the template, and write the config into 105 // NetworkPluginConfDir. 106 // Ideally the cni config should be placed by system admin or cni daemon like calico, 107 // weaveworks etc. However, there are still users using kubenet 108 // (https://kubernetes.io/docs/concepts/cluster-administration/network-plugins/#kubenet) 109 // today, who don't have a cni daemonset in production. NetworkPluginConfTemplate is 110 // a temporary backward-compatible solution for them. 111 // TODO(random-liu): Deprecate this option when kubenet is deprecated. 112 NetworkPluginConfTemplate string `toml:"conf_template" json:"confTemplate"` 113} 114 115// Mirror contains the config related to the registry mirror 116type Mirror struct { 117 // Endpoints are endpoints for a namespace. CRI plugin will try the endpoints 118 // one by one until a working one is found. The endpoint must be a valid url 119 // with host specified. 120 // The scheme, host and path from the endpoint URL will be used. 121 Endpoints []string `toml:"endpoint" json:"endpoint"` 122} 123 124// AuthConfig contains the config related to authentication to a specific registry 125type AuthConfig struct { 126 // Username is the username to login the registry. 127 Username string `toml:"username" json:"username"` 128 // Password is the password to login the registry. 129 Password string `toml:"password" json:"password"` 130 // Auth is a base64 encoded string from the concatenation of the username, 131 // a colon, and the password. 132 Auth string `toml:"auth" json:"auth"` 133 // IdentityToken is used to authenticate the user and get 134 // an access token for the registry. 135 IdentityToken string `toml:"identitytoken" json:"identitytoken"` 136} 137 138// TLSConfig contains the CA/Cert/Key used for a registry 139type TLSConfig struct { 140 InsecureSkipVerify bool `toml:"insecure_skip_verify" json:"insecure_skip_verify"` 141 CAFile string `toml:"ca_file" json:"caFile"` 142 CertFile string `toml:"cert_file" json:"certFile"` 143 KeyFile string `toml:"key_file" json:"keyFile"` 144} 145 146// Registry is registry settings configured 147type Registry struct { 148 // Mirrors are namespace to mirror mapping for all namespaces. 149 Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"` 150 // Configs are configs for each registry. 151 // The key is the domain name or IP of the registry. 152 Configs map[string]RegistryConfig `toml:"configs" json:"configs"` 153 154 // Auths are registry endpoint to auth config mapping. The registry endpoint must 155 // be a valid url with host specified. 156 // DEPRECATED: Use Configs instead. Remove in containerd 1.4. 157 Auths map[string]AuthConfig `toml:"auths" json:"auths"` 158 // Headers adds additional HTTP headers that get sent to all registries 159 Headers map[string][]string `toml:"headers" json:"headers"` 160} 161 162// RegistryConfig contains configuration used to communicate with the registry. 163type RegistryConfig struct { 164 // Auth contains information to authenticate to the registry. 165 Auth *AuthConfig `toml:"auth" json:"auth"` 166 // TLS is a pair of CA/Cert/Key which then are used when creating the transport 167 // that communicates with the registry. 168 TLS *TLSConfig `toml:"tls" json:"tls"` 169} 170 171// ImageDecryption contains configuration to handling decryption of encrypted container images. 172type ImageDecryption struct { 173 // KeyModel specifies the trust model of where keys should reside. 174 // 175 // Details of field usage can be found in: 176 // https://github.com/containerd/cri/tree/master/docs/config.md 177 // 178 // Details of key models can be found in: 179 // https://github.com/containerd/cri/tree/master/docs/decryption.md 180 KeyModel string `toml:"key_model" json:"keyModel"` 181} 182 183// PluginConfig contains toml config related to CRI plugin, 184// it is a subset of Config. 185type PluginConfig struct { 186 // ContainerdConfig contains config related to containerd 187 ContainerdConfig `toml:"containerd" json:"containerd"` 188 // CniConfig contains config related to cni 189 CniConfig `toml:"cni" json:"cni"` 190 // Registry contains config related to the registry 191 Registry Registry `toml:"registry" json:"registry"` 192 // ImageDecryption contains config related to handling decryption of encrypted container images 193 ImageDecryption `toml:"image_decryption" json:"imageDecryption"` 194 // DisableTCPService disables serving CRI on the TCP server. 195 DisableTCPService bool `toml:"disable_tcp_service" json:"disableTCPService"` 196 // StreamServerAddress is the ip address streaming server is listening on. 197 StreamServerAddress string `toml:"stream_server_address" json:"streamServerAddress"` 198 // StreamServerPort is the port streaming server is listening on. 199 StreamServerPort string `toml:"stream_server_port" json:"streamServerPort"` 200 // StreamIdleTimeout is the maximum time a streaming connection 201 // can be idle before the connection is automatically closed. 202 // The string is in the golang duration format, see: 203 // https://golang.org/pkg/time/#ParseDuration 204 StreamIdleTimeout string `toml:"stream_idle_timeout" json:"streamIdleTimeout"` 205 // EnableSelinux indicates to enable the selinux support. 206 EnableSelinux bool `toml:"enable_selinux" json:"enableSelinux"` 207 // SelinuxCategoryRange allows the upper bound on the category range to be set. 208 // If not specified or set to 0, defaults to 1024 from the selinux package. 209 SelinuxCategoryRange int `toml:"selinux_category_range" json:"selinuxCategoryRange"` 210 // SandboxImage is the image used by sandbox container. 211 SandboxImage string `toml:"sandbox_image" json:"sandboxImage"` 212 // StatsCollectPeriod is the period (in seconds) of snapshots stats collection. 213 StatsCollectPeriod int `toml:"stats_collect_period" json:"statsCollectPeriod"` 214 // SystemdCgroup enables systemd cgroup support. 215 // This only works for runtime type "io.containerd.runtime.v1.linux". 216 // DEPRECATED: config runc runtime handler instead. Remove when shim v1 is deprecated. 217 SystemdCgroup bool `toml:"systemd_cgroup" json:"systemdCgroup"` 218 // EnableTLSStreaming indicates to enable the TLS streaming support. 219 EnableTLSStreaming bool `toml:"enable_tls_streaming" json:"enableTLSStreaming"` 220 // X509KeyPairStreaming is a x509 key pair used for TLS streaming 221 X509KeyPairStreaming `toml:"x509_key_pair_streaming" json:"x509KeyPairStreaming"` 222 // MaxContainerLogLineSize is the maximum log line size in bytes for a container. 223 // Log line longer than the limit will be split into multiple lines. Non-positive 224 // value means no limit. 225 MaxContainerLogLineSize int `toml:"max_container_log_line_size" json:"maxContainerLogSize"` 226 // DisableCgroup indicates to disable the cgroup support. 227 // This is useful when the containerd does not have permission to access cgroup. 228 DisableCgroup bool `toml:"disable_cgroup" json:"disableCgroup"` 229 // DisableApparmor indicates to disable the apparmor support. 230 // This is useful when the containerd does not have permission to access Apparmor. 231 DisableApparmor bool `toml:"disable_apparmor" json:"disableApparmor"` 232 // RestrictOOMScoreAdj indicates to limit the lower bound of OOMScoreAdj to the containerd's 233 // current OOMScoreADj. 234 // This is useful when the containerd does not have permission to decrease OOMScoreAdj. 235 RestrictOOMScoreAdj bool `toml:"restrict_oom_score_adj" json:"restrictOOMScoreAdj"` 236 // MaxConcurrentDownloads restricts the number of concurrent downloads for each image. 237 MaxConcurrentDownloads int `toml:"max_concurrent_downloads" json:"maxConcurrentDownloads"` 238 // DisableProcMount disables Kubernetes ProcMount support. This MUST be set to `true` 239 // when using containerd with Kubernetes <=1.11. 240 DisableProcMount bool `toml:"disable_proc_mount" json:"disableProcMount"` 241 // UnsetSeccompProfile is the profile containerd/cri will use If the provided seccomp profile is 242 // unset (`""`) for a container (default is `unconfined`) 243 UnsetSeccompProfile string `toml:"unset_seccomp_profile" json:"unsetSeccompProfile"` 244 // TolerateMissingHugetlbController if set to false will error out on create/update 245 // container requests with huge page limits if the cgroup controller for hugepages is not present. 246 // This helps with supporting Kubernetes <=1.18 out of the box. (default is `true`) 247 TolerateMissingHugetlbController bool `toml:"tolerate_missing_hugetlb_controller" json:"tolerateMissingHugetlbController"` 248 // DisableHugetlbController indicates to silently disable the hugetlb controller, even when it is 249 // present in /sys/fs/cgroup/cgroup.controllers. 250 // This helps with running rootless mode + cgroup v2 + systemd but without hugetlb delegation. 251 DisableHugetlbController bool `toml:"disable_hugetlb_controller" json:"disableHugetlbController"` 252 // IgnoreImageDefinedVolumes ignores volumes defined by the image. Useful for better resource 253 // isolation, security and early detection of issues in the mount configuration when using 254 // ReadOnlyRootFilesystem since containers won't silently mount a temporary volume. 255 IgnoreImageDefinedVolumes bool `toml:"ignore_image_defined_volumes" json:"ignoreImageDefinedVolumes"` 256} 257 258// X509KeyPairStreaming contains the x509 configuration for streaming 259type X509KeyPairStreaming struct { 260 // TLSCertFile is the path to a certificate file 261 TLSCertFile string `toml:"tls_cert_file" json:"tlsCertFile"` 262 // TLSKeyFile is the path to a private key file 263 TLSKeyFile string `toml:"tls_key_file" json:"tlsKeyFile"` 264} 265 266// Config contains all configurations for cri server. 267type Config struct { 268 // PluginConfig is the config for CRI plugin. 269 PluginConfig 270 // ContainerdRootDir is the root directory path for containerd. 271 ContainerdRootDir string `json:"containerdRootDir"` 272 // ContainerdEndpoint is the containerd endpoint path. 273 ContainerdEndpoint string `json:"containerdEndpoint"` 274 // RootDir is the root directory path for managing cri plugin files 275 // (metadata checkpoint etc.) 276 RootDir string `json:"rootDir"` 277 // StateDir is the root directory path for managing volatile pod/container data 278 StateDir string `json:"stateDir"` 279} 280 281const ( 282 // RuntimeUntrusted is the implicit runtime defined for ContainerdConfig.UntrustedWorkloadRuntime 283 RuntimeUntrusted = "untrusted" 284 // RuntimeDefault is the implicit runtime defined for ContainerdConfig.DefaultRuntime 285 RuntimeDefault = "default" 286 // KeyModelNode is the key model where key for encrypted images reside 287 // on the worker nodes 288 KeyModelNode = "node" 289) 290 291// ValidatePluginConfig validates the given plugin configuration. 292func ValidatePluginConfig(ctx context.Context, c *PluginConfig) error { 293 if c.ContainerdConfig.Runtimes == nil { 294 c.ContainerdConfig.Runtimes = make(map[string]Runtime) 295 } 296 297 // Validation for deprecated untrusted_workload_runtime. 298 if c.ContainerdConfig.UntrustedWorkloadRuntime.Type != "" { 299 log.G(ctx).Warning("`untrusted_workload_runtime` is deprecated, please use `untrusted` runtime in `runtimes` instead") 300 if _, ok := c.ContainerdConfig.Runtimes[RuntimeUntrusted]; ok { 301 return errors.Errorf("conflicting definitions: configuration includes both `untrusted_workload_runtime` and `runtimes[%q]`", RuntimeUntrusted) 302 } 303 c.ContainerdConfig.Runtimes[RuntimeUntrusted] = c.ContainerdConfig.UntrustedWorkloadRuntime 304 } 305 306 // Validation for deprecated default_runtime field. 307 if c.ContainerdConfig.DefaultRuntime.Type != "" { 308 log.G(ctx).Warning("`default_runtime` is deprecated, please use `default_runtime_name` to reference the default configuration you have defined in `runtimes`") 309 c.ContainerdConfig.DefaultRuntimeName = RuntimeDefault 310 c.ContainerdConfig.Runtimes[RuntimeDefault] = c.ContainerdConfig.DefaultRuntime 311 } 312 313 // Validation for default_runtime_name 314 if c.ContainerdConfig.DefaultRuntimeName == "" { 315 return errors.New("`default_runtime_name` is empty") 316 } 317 if _, ok := c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName]; !ok { 318 return errors.New("no corresponding runtime configured in `runtimes` for `default_runtime_name`") 319 } 320 321 // Validation for deprecated runtime options. 322 if c.SystemdCgroup { 323 if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { 324 return errors.Errorf("`systemd_cgroup` only works for runtime %s", plugin.RuntimeLinuxV1) 325 } 326 log.G(ctx).Warning("`systemd_cgroup` is deprecated, please use runtime `options` instead") 327 } 328 if c.NoPivot { 329 if c.ContainerdConfig.Runtimes[c.ContainerdConfig.DefaultRuntimeName].Type != plugin.RuntimeLinuxV1 { 330 return errors.Errorf("`no_pivot` only works for runtime %s", plugin.RuntimeLinuxV1) 331 } 332 // NoPivot can't be deprecated yet, because there is no alternative config option 333 // for `io.containerd.runtime.v1.linux`. 334 } 335 for _, r := range c.ContainerdConfig.Runtimes { 336 if r.Engine != "" { 337 if r.Type != plugin.RuntimeLinuxV1 { 338 return errors.Errorf("`runtime_engine` only works for runtime %s", plugin.RuntimeLinuxV1) 339 } 340 log.G(ctx).Warning("`runtime_engine` is deprecated, please use runtime `options` instead") 341 } 342 if r.Root != "" { 343 if r.Type != plugin.RuntimeLinuxV1 { 344 return errors.Errorf("`runtime_root` only works for runtime %s", plugin.RuntimeLinuxV1) 345 } 346 log.G(ctx).Warning("`runtime_root` is deprecated, please use runtime `options` instead") 347 } 348 } 349 350 // Validation for deprecated auths options and mapping it to configs. 351 if len(c.Registry.Auths) != 0 { 352 if c.Registry.Configs == nil { 353 c.Registry.Configs = make(map[string]RegistryConfig) 354 } 355 for endpoint, auth := range c.Registry.Auths { 356 auth := auth 357 u, err := url.Parse(endpoint) 358 if err != nil { 359 return errors.Wrapf(err, "failed to parse registry url %q from `registry.auths`", endpoint) 360 } 361 if u.Scheme != "" { 362 // Do not include the scheme in the new registry config. 363 endpoint = u.Host 364 } 365 config := c.Registry.Configs[endpoint] 366 config.Auth = &auth 367 c.Registry.Configs[endpoint] = config 368 } 369 log.G(ctx).Warning("`auths` is deprecated, please use registry`configs` instead") 370 } 371 372 // Validation for stream_idle_timeout 373 if c.StreamIdleTimeout != "" { 374 if _, err := time.ParseDuration(c.StreamIdleTimeout); err != nil { 375 return errors.Wrap(err, "invalid stream idle timeout") 376 } 377 } 378 return nil 379} 380