feat: environment variables via the kernel arguments
Unify getting environment variables, support passing environment variables via kernel args. Fixes #6984 See #6999 For META this will be used to pass environment variables to the installer for ISO images (or PXE booting). Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
parent
94c24ca64e
commit
ea0e9bdbe4
@ -138,6 +138,18 @@ Talos API was extended to support retrieving a list of network connections (sock
|
||||
Talos now supports loading network configuration on VMWare platform from the `metadata` key.
|
||||
See [CAPV IPAM Support](https://github.com/kubernetes-sigs/cluster-api-provider-vsphere/blob/main/docs/proposal/20220929-ipam-support.md) and
|
||||
[Talos issue 6708](https://github.com/siderolabs/talos/issues/6708) for details.
|
||||
"""
|
||||
|
||||
[notes.env]
|
||||
title = "Kernel Argument `talos.environment`"
|
||||
description="""\
|
||||
Talos now supports passing environment variables via `talos.environment` kernel argument.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
talos.environment=http_proxy=http://proxy.example.com:8080 talos.environment=https_proxy=http://proxy.example.com:8080
|
||||
```
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
@ -55,6 +55,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/maintenance"
|
||||
"github.com/siderolabs/talos/internal/pkg/console"
|
||||
"github.com/siderolabs/talos/internal/pkg/cri"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/internal/pkg/etcd"
|
||||
"github.com/siderolabs/talos/internal/pkg/install"
|
||||
"github.com/siderolabs/talos/internal/pkg/meta"
|
||||
@ -739,7 +740,9 @@ func DiskSizeCheck(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
|
||||
// SetUserEnvVars represents the SetUserEnvVars task.
|
||||
func SetUserEnvVars(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
|
||||
return func(ctx context.Context, logger *log.Logger, r runtime.Runtime) (err error) {
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
for _, env := range environment.Get(r.Config()) {
|
||||
key, val, _ := strings.Cut(env, "=")
|
||||
|
||||
if err = os.Setenv(key, val); err != nil {
|
||||
return fmt.Errorf("failed to set enivronment variable: %w", err)
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/containerd"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/pkg/conditions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||
@ -160,7 +161,9 @@ func (o *APID) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
|
||||
env := []string{}
|
||||
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
for _, value := range environment.Get(r.Config()) {
|
||||
key, _, _ := strings.Cut(value, "=")
|
||||
|
||||
switch strings.ToLower(key) {
|
||||
// explicitly exclude proxy variables from apid since this will
|
||||
// negatively impact grpc connections.
|
||||
@ -170,7 +173,7 @@ func (o *APID) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
case "http_proxy":
|
||||
case "https_proxy":
|
||||
default:
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
env = append(env, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/process"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/pkg/conditions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
)
|
||||
@ -93,14 +94,6 @@ func (c *Containerd) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
},
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
|
||||
if r.Config() != nil {
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
}
|
||||
|
||||
debug := false
|
||||
|
||||
if r.Config() != nil {
|
||||
@ -111,7 +104,7 @@ func (c *Containerd) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
debug,
|
||||
args,
|
||||
runner.WithLoggingManager(r.Logging()),
|
||||
runner.WithEnv(env),
|
||||
runner.WithEnv(environment.Get(r.Config())),
|
||||
runner.WithOOMScoreAdj(-999),
|
||||
runner.WithCgroupPath(constants.CgroupSystemRuntime),
|
||||
runner.WithDroppedCapabilities(constants.DefaultDroppedCapabilities),
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/process"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/pkg/conditions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||
@ -93,16 +94,11 @@ func (c *CRI) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
},
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
|
||||
return restart.New(process.NewRunner(
|
||||
r.Config().Debug(),
|
||||
args,
|
||||
runner.WithLoggingManager(r.Logging()),
|
||||
runner.WithEnv(env),
|
||||
runner.WithEnv(environment.Get(r.Config())),
|
||||
runner.WithOOMScoreAdj(-500),
|
||||
runner.WithCgroupPath(constants.CgroupPodRuntime),
|
||||
runner.WithDroppedCapabilities(constants.DefaultDroppedCapabilities),
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/containerd"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/containers/image"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/internal/pkg/etcd"
|
||||
"github.com/siderolabs/talos/internal/pkg/meta"
|
||||
"github.com/siderolabs/talos/pkg/argsbuilder"
|
||||
@ -185,10 +186,7 @@ func (e *Etcd) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
{Type: "bind", Destination: constants.EtcdDataPath, Source: constants.EtcdDataPath, Options: []string{"rbind", "rw"}},
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
env := environment.Get(r.Config())
|
||||
|
||||
if goruntime.GOARCH == "arm64" {
|
||||
env = append(env, "ETCD_UNSUPPORTED_ARCH=arm64")
|
||||
|
@ -7,7 +7,6 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -20,6 +19,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/containerd"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/capability"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/internal/pkg/mount"
|
||||
"github.com/siderolabs/talos/pkg/conditions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
@ -150,11 +150,6 @@ func (svc *Extension) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
}
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
|
||||
var restartType restart.Type
|
||||
|
||||
switch svc.Spec.Restart {
|
||||
@ -172,7 +167,7 @@ func (svc *Extension) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
runner.WithLoggingManager(r.Logging()),
|
||||
runner.WithNamespace(constants.SystemContainerdNamespace),
|
||||
runner.WithContainerdAddress(constants.SystemContainerdAddress),
|
||||
runner.WithEnv(env),
|
||||
runner.WithEnv(environment.Get(r.Config())),
|
||||
runner.WithOCISpecOpts(svc.getOCIOptions()...),
|
||||
runner.WithOOMScoreAdj(-600),
|
||||
),
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/capability"
|
||||
"github.com/siderolabs/talos/internal/pkg/containers/image"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/pkg/conditions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1/machine"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
@ -141,18 +142,13 @@ func (k *Kubelet) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
mounts = append(mounts, mount)
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
|
||||
return restart.New(containerd.NewRunner(
|
||||
r.Config().Debug() && r.Config().Machine().Type() == machine.TypeWorker, // enable debug logs only for the worker nodes
|
||||
&args,
|
||||
runner.WithLoggingManager(r.Logging()),
|
||||
runner.WithNamespace(constants.SystemContainerdNamespace),
|
||||
runner.WithContainerImage(spec.Image),
|
||||
runner.WithEnv(env),
|
||||
runner.WithEnv(environment.Get(r.Config())),
|
||||
runner.WithOCISpecOpts(
|
||||
containerd.WithRootfsPropagation("shared"),
|
||||
oci.WithCgroup(constants.CgroupKubelet),
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/containerd"
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/restart"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/pkg/conditions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||
@ -138,10 +139,7 @@ func (t *Trustd) Runner(r runtime.Runtime) (runner.Runner, error) {
|
||||
{Type: "bind", Destination: filepath.Dir(constants.TrustdRuntimeSocketPath), Source: filepath.Dir(constants.TrustdRuntimeSocketPath), Options: []string{"rbind", "ro"}},
|
||||
}
|
||||
|
||||
env := []string{}
|
||||
for key, val := range r.Config().Machine().Env() {
|
||||
env = append(env, fmt.Sprintf("%s=%s", key, val))
|
||||
}
|
||||
env := environment.Get(r.Config())
|
||||
|
||||
if debug.RaceEnabled {
|
||||
env = append(env, "GORACE=halt_on_error=1")
|
||||
|
44
internal/pkg/environment/environment.go
Normal file
44
internal/pkg/environment/environment.go
Normal file
@ -0,0 +1,44 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package environment provides a set of functions to get environment variables.
|
||||
package environment
|
||||
|
||||
import (
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
)
|
||||
|
||||
// Get the desired set of the environment variables based on kernel cmdline and machine config.
|
||||
//
|
||||
// The returned value is a list of strings in the form of "key=value".
|
||||
func Get(cfg config.Provider) []string {
|
||||
return GetCmdline(procfs.ProcCmdline(), cfg)
|
||||
}
|
||||
|
||||
// GetCmdline the desired set of the environment variables based on kernel cmdline.
|
||||
func GetCmdline(cmdline *procfs.Cmdline, cfg config.Provider) []string {
|
||||
var result []string
|
||||
|
||||
param := cmdline.Get(constants.KernelParamEnvironment)
|
||||
|
||||
for idx := 0; ; idx++ {
|
||||
val := param.Get(idx)
|
||||
if val == nil {
|
||||
break
|
||||
}
|
||||
|
||||
result = append(result, *val)
|
||||
}
|
||||
|
||||
if cfg != nil {
|
||||
for k, v := range cfg.Machine().Env() {
|
||||
result = append(result, k+"="+v)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
82
internal/pkg/environment/environment_test.go
Normal file
82
internal/pkg/environment/environment_test.go
Normal file
@ -0,0 +1,82 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package environment_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
cmdline string
|
||||
cfg map[string]string
|
||||
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
},
|
||||
{
|
||||
name: "machine config only",
|
||||
cfg: map[string]string{
|
||||
"http_proxy": "http://proxy.example.com:8080",
|
||||
},
|
||||
expected: []string{
|
||||
"http_proxy=http://proxy.example.com:8080",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cmdline only",
|
||||
cmdline: "talos.environment=foo=bar talos.environment=bar=baz",
|
||||
expected: []string{
|
||||
"foo=bar",
|
||||
"bar=baz",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cmdline and machine config",
|
||||
cmdline: "talos.environment=foo=bar",
|
||||
cfg: map[string]string{
|
||||
"http_proxy": "http://proxy.example.com:8080",
|
||||
},
|
||||
expected: []string{
|
||||
"foo=bar",
|
||||
"http_proxy=http://proxy.example.com:8080",
|
||||
},
|
||||
},
|
||||
} {
|
||||
test := test
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cmdline := procfs.NewCmdline(test.cmdline)
|
||||
|
||||
var cfg config.Provider
|
||||
|
||||
if test.cfg != nil {
|
||||
cfg = &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineEnv: test.cfg,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
result := environment.GetCmdline(cmdline, cfg)
|
||||
|
||||
assert.Equal(t, test.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ import (
|
||||
containerdrunner "github.com/siderolabs/talos/internal/app/machined/pkg/system/runner/containerd"
|
||||
"github.com/siderolabs/talos/internal/pkg/capability"
|
||||
"github.com/siderolabs/talos/internal/pkg/containers/image"
|
||||
"github.com/siderolabs/talos/internal/pkg/environment"
|
||||
"github.com/siderolabs/talos/internal/pkg/extensions"
|
||||
machineapi "github.com/siderolabs/talos/pkg/machinery/api/machine"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config"
|
||||
@ -165,24 +166,16 @@ func RunInstallerContainer(disk, platform, ref string, cfg config.Provider, opts
|
||||
args = append(args, "--extra-kernel-arg", arg)
|
||||
}
|
||||
|
||||
if c := procfs.ProcCmdline().Get(constants.KernelParamSideroLink).First(); c != nil {
|
||||
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", constants.KernelParamSideroLink, *c))
|
||||
}
|
||||
|
||||
if c := procfs.ProcCmdline().Get(constants.KernelParamEventsSink).First(); c != nil {
|
||||
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", constants.KernelParamEventsSink, *c))
|
||||
}
|
||||
|
||||
if c := procfs.ProcCmdline().Get(constants.KernelParamLoggingKernel).First(); c != nil {
|
||||
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", constants.KernelParamLoggingKernel, *c))
|
||||
}
|
||||
|
||||
if c := procfs.ProcCmdline().Get(constants.KernelParamEquinixMetalEvents).First(); c != nil {
|
||||
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", constants.KernelParamEquinixMetalEvents, *c))
|
||||
}
|
||||
|
||||
if c := procfs.ProcCmdline().Get(constants.KernelParamDashboardDisabled).First(); c != nil {
|
||||
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", constants.KernelParamDashboardDisabled, *c))
|
||||
for _, preservedArg := range []string{
|
||||
constants.KernelParamSideroLink,
|
||||
constants.KernelParamEventsSink,
|
||||
constants.KernelParamLoggingKernel,
|
||||
constants.KernelParamEquinixMetalEvents,
|
||||
constants.KernelParamDashboardDisabled,
|
||||
} {
|
||||
if c := procfs.ProcCmdline().Get(preservedArg).First(); c != nil {
|
||||
args = append(args, "--extra-kernel-arg", fmt.Sprintf("%s=%s", preservedArg, *c))
|
||||
}
|
||||
}
|
||||
|
||||
specOpts := []oci.SpecOpts{
|
||||
@ -203,6 +196,7 @@ func RunInstallerContainer(disk, platform, ref string, cfg config.Provider, opts
|
||||
oci.WithApparmorProfile(""),
|
||||
oci.WithSeccompUnconfined,
|
||||
oci.WithAllDevicesAllowed,
|
||||
oci.WithEnv(environment.Get(cfg)),
|
||||
}
|
||||
|
||||
containerOpts := []containerd.NewContainerOpts{
|
||||
|
@ -52,6 +52,9 @@ const (
|
||||
// KernelParamDashboardDisabled is the kernel parameter name for disabling the dashboard.
|
||||
KernelParamDashboardDisabled = "talos.dashboard.disabled"
|
||||
|
||||
// KernelParamEnvironment is the kernel parameter name for passing process environment.
|
||||
KernelParamEnvironment = "talos.environment"
|
||||
|
||||
// BoardNone indicates that the install is not for a specific board.
|
||||
BoardNone = "none"
|
||||
|
||||
|
@ -225,3 +225,14 @@ If you set `talos.dashboard.disabled=1`, this behavior will be disabled.
|
||||
Kernel logs will be sent to the currently active console and the dashboard will not be started.
|
||||
|
||||
It is set to be `1` by default on SBCs.
|
||||
|
||||
#### `talos.environment`
|
||||
|
||||
Each value of the argument sets a default environment variable.
|
||||
The expected format is `key=value`.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
talos.environment=http_proxy=http://proxy.example.com:8080 talos.environment=https_proxy=http://proxy.example.com:8080
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user