Skip to content

Commit

Permalink
test: add json logs test environment
Browse files Browse the repository at this point in the history
Add an option to `talosctl cluster create` to start a JSON log receiver,
and enabled it optionally.

Enable in `integration-qemu`.

See #9510

Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
smira committed Oct 17, 2024
1 parent 71faa32 commit bc4c21f
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-09-23T13:32:15Z by kres 8be5fa7.
# Generated on 2024-10-16T13:22:04Z by kres 34e72ac.

name: default
concurrency:
Expand Down Expand Up @@ -2775,6 +2775,7 @@ jobs:
QEMU_EXTRA_DISKS_DRIVERS: ide,nvme
QEMU_EXTRA_DISKS_SIZE: "10240"
WITH_CONFIG_PATCH_WORKER: '@hack/test/patches/ephemeral-nvme.yaml:@hack/test/patches/dm-raid-module.yaml'
WITH_JSON_LOGS: "true"
run: |
sudo -E make e2e-qemu
- name: save artifacts
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/integration-qemu-cron.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-09-20T16:31:33Z by kres 8be5fa7.
# Generated on 2024-10-16T13:22:04Z by kres 34e72ac.

name: integration-qemu-cron
concurrency:
Expand Down Expand Up @@ -85,6 +85,7 @@ jobs:
QEMU_EXTRA_DISKS_DRIVERS: ide,nvme
QEMU_EXTRA_DISKS_SIZE: "10240"
WITH_CONFIG_PATCH_WORKER: '@hack/test/patches/ephemeral-nvme.yaml:@hack/test/patches/dm-raid-module.yaml'
WITH_JSON_LOGS: "true"
run: |
sudo -E make e2e-qemu
- name: save artifacts
Expand Down
1 change: 1 addition & 0 deletions .kres.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ spec:
QEMU_EXTRA_DISKS_SIZE: "10240"
QEMU_EXTRA_DISKS_DRIVERS: "ide,nvme"
WITH_CONFIG_PATCH_WORKER: "@hack/test/patches/ephemeral-nvme.yaml:@hack/test/patches/dm-raid-module.yaml"
WITH_JSON_LOGS: "true"
- name: save-talos-logs
conditions:
- always
Expand Down
32 changes: 31 additions & 1 deletion cmd/talosctl/cmd/mgmt/cluster/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
"github.com/siderolabs/talos/pkg/machinery/config/bundle"
"github.com/siderolabs/talos/pkg/machinery/config/configloader"
"github.com/siderolabs/talos/pkg/machinery/config/configpatcher"
"github.com/siderolabs/talos/pkg/machinery/config/container"
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
"github.com/siderolabs/talos/pkg/machinery/config/generate"
"github.com/siderolabs/talos/pkg/machinery/config/machine"
Expand Down Expand Up @@ -188,6 +189,7 @@ var (
withFirewall string
withUUIDHostnames bool
withSiderolinkAgent agentFlag
withJSONLogs bool
)

// createCmd represents the cluster up command.
Expand Down Expand Up @@ -578,7 +580,7 @@ func create(ctx context.Context) error {
return err
}

port := 4050
const port = 4050

keys = append(keys, &v1alpha1.EncryptionKey{
KeyKMS: &v1alpha1.EncryptionKeyKMS{
Expand Down Expand Up @@ -776,6 +778,33 @@ func create(ctx context.Context) error {
configBundleOpts = append(configBundleOpts, bundle.WithPatch([]configpatcher.Patch{configpatcher.NewStrategicMergePatch(trustedRootsPatch)}))
}

if withJSONLogs {
const port = 4003

provisionOptions = append(provisionOptions, provision.WithJSONLogs(nethelpers.JoinHostPort(gatewayIPs[0].String(), port)))

cfg := container.NewV1Alpha1(
&v1alpha1.Config{
ConfigVersion: "v1alpha1",
MachineConfig: &v1alpha1.MachineConfig{
MachineLogging: &v1alpha1.LoggingConfig{
LoggingDestinations: []v1alpha1.LoggingDestination{
{
LoggingEndpoint: &v1alpha1.Endpoint{
URL: &url.URL{
Scheme: "tcp",
Host: nethelpers.JoinHostPort(gatewayIPs[0].String(), port),
},
},
LoggingFormat: "json_lines",
},
},
},
},
})
configBundleOpts = append(configBundleOpts, bundle.WithPatch([]configpatcher.Patch{configpatcher.NewStrategicMergePatch(cfg)}))
}

configBundle, err := bundle.NewBundle(configBundleOpts...)
if err != nil {
return err
Expand Down Expand Up @@ -1256,6 +1285,7 @@ func init() {
createCmd.Flags().StringVar(&withFirewall, firewallFlag, "", "inject firewall rules into the cluster, value is default policy - accept/block (QEMU only)")
createCmd.Flags().BoolVar(&withUUIDHostnames, "with-uuid-hostnames", false, "use machine UUIDs as default hostnames (QEMU only)")
createCmd.Flags().Var(&withSiderolinkAgent, "with-siderolink", "enables the use of siderolink agent as configuration apply mechanism. `true` or `wireguard` enables the agent, `tunnel` enables the agent with grpc tunneling") //nolint:lll
createCmd.Flags().BoolVar(&withJSONLogs, "with-json-logs", false, "enable JSON logs receiver and configure Talos to send logs there")

createCmd.MarkFlagsMutuallyExclusive(inputDirFlag, nodeInstallImageFlag)
createCmd.MarkFlagsMutuallyExclusive(inputDirFlag, configDebugFlag)
Expand Down
76 changes: 76 additions & 0 deletions cmd/talosctl/cmd/mgmt/json_logs_launch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// 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 mgmt

import (
"bufio"
"log"
"net"
"net/netip"

"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)

var jsonLogsLaunchCmdFlags struct {
addr string
}

// jsonLogsLaunchCmd represents the kms-launch command.
var jsonLogsLaunchCmd = &cobra.Command{
Use: "json-logs-launch",
Short: "Internal command used by QEMU provisioner",
Long: ``,
Args: cobra.NoArgs,
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
lis, err := net.Listen("tcp", jsonLogsLaunchCmdFlags.addr)
if err != nil {
return err
}

log.Printf("starting JSON logs server on %s", jsonLogsLaunchCmdFlags.addr)

eg, ctx := errgroup.WithContext(cmd.Context())

eg.Go(func() error {
for {
conn, err := lis.Accept()
if err != nil {
return err
}

go func() {
defer conn.Close() //nolint:errcheck

remoteAddr := conn.RemoteAddr().String()

if addr, err := netip.ParseAddrPort(remoteAddr); err == nil {
remoteAddr = addr.Addr().String()
}

scanner := bufio.NewScanner(conn)

for scanner.Scan() {
log.Printf("%s: %s", remoteAddr, scanner.Text())
}
}()
}
})

eg.Go(func() error {
<-ctx.Done()

return lis.Close()
})

return eg.Wait()
},
}

func init() {
jsonLogsLaunchCmd.Flags().StringVar(&jsonLogsLaunchCmdFlags.addr, "addr", "localhost:3000", "JSON logs listen address")
addCommand(jsonLogsLaunchCmd)
}
2 changes: 1 addition & 1 deletion cmd/talosctl/cmd/mgmt/kms_launch.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ var kmsLaunchCmd = &cobra.Command{
return nil
})

return s.Serve(lis)
return eg.Wait()
},
}

Expand Down
6 changes: 6 additions & 0 deletions hack/test/e2e-qemu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ case "${WITH_VIRTUAL_IP:-false}" in
;;
esac

case "${WITH_JSON_LOGS:-false}" in
true)
QEMU_FLAGS+=("--with-json-logs")
;;
esac

case "${WITH_CLUSTER_DISCOVERY:-true}" in
false)
QEMU_FLAGS+=("--with-cluster-discovery=false" "--kubeprism-port=0") # disable both KubePrism and cluster discovery
Expand Down
12 changes: 11 additions & 1 deletion pkg/provision/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ func WithKMS(endpoint string) Option {
}
}

// WithJSONLogs specifies endpoint to send logs in JSON format.
func WithJSONLogs(endpoint string) Option {
return func(o *Options) error {
o.JSONLogsEndpoint = endpoint

return nil
}
}

// WithSiderolinkAgent enables or disables siderolink agent.
func WithSiderolinkAgent(v bool) Option {
return func(o *Options) error {
Expand Down Expand Up @@ -165,7 +174,8 @@ type Options struct {
DockerPortsHostIP string
DeleteStateOnErr bool

KMSEndpoint string
KMSEndpoint string
JSONLogsEndpoint string

SiderolinkEnabled bool
}
Expand Down
10 changes: 9 additions & 1 deletion pkg/provision/providers/qemu/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

// Create Talos cluster as a set of qemu VMs.
//
//nolint:gocyclo
//nolint:gocyclo,cyclop
func (p *provisioner) Create(ctx context.Context, request provision.ClusterRequest, opts ...provision.Option) (provision.Cluster, error) {
options := provision.DefaultOptions()

Expand Down Expand Up @@ -78,6 +78,14 @@ func (p *provisioner) Create(ctx context.Context, request provision.ClusterReque
}
}

if options.JSONLogsEndpoint != "" {
fmt.Fprintln(options.LogWriter, "creating JSON logs server")

if err = p.CreateJSONLogs(state, request, options); err != nil {
return nil, fmt.Errorf("error creating JSON logs server: %w", err)
}
}

fmt.Fprintln(options.LogWriter, "creating dhcpd")

if err = p.CreateDHCPd(state, request); err != nil {
Expand Down
6 changes: 6 additions & 0 deletions pkg/provision/providers/qemu/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ func (p *provisioner) Destroy(ctx context.Context, cluster provision.Cluster, op
return err
}

fmt.Fprintln(options.LogWriter, "removing json logs")

if err := p.DestroyJSONLogs(state); err != nil {
return err
}

fmt.Fprintln(options.LogWriter, "removing network")

if err := p.DestroyNetwork(state); err != nil {
Expand Down
68 changes: 68 additions & 0 deletions pkg/provision/providers/vm/json-logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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 vm

import (
"crypto/rand"
"fmt"
"io"
"os"
"os/exec"
"strconv"
"syscall"

"github.com/siderolabs/talos/pkg/provision"
)

const (
jsonLogsPid = "json-logs.pid"
jsonLogsLog = "json-logs.log"
)

// CreateJSONLogs creates JSON logs server.
func (p *Provisioner) CreateJSONLogs(state *State, clusterReq provision.ClusterRequest, options provision.Options) error {
pidPath := state.GetRelativePath(jsonLogsPid)

logFile, err := os.OpenFile(state.GetRelativePath(jsonLogsLog), os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o666)
if err != nil {
return err
}

defer logFile.Close() //nolint:errcheck

key := make([]byte, 32)
if _, err = io.ReadFull(rand.Reader, key); err != nil {
return err
}

args := []string{
"json-logs-launch",
"--addr", options.JSONLogsEndpoint,
}

cmd := exec.Command(clusterReq.SelfExecutable, args...)
cmd.Stdout = logFile
cmd.Stderr = logFile
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true, // daemonize
}

if err = cmd.Start(); err != nil {
return err
}

if err = os.WriteFile(pidPath, []byte(strconv.Itoa(cmd.Process.Pid)), os.ModePerm); err != nil {
return fmt.Errorf("error writing LB PID file: %w", err)
}

return nil
}

// DestroyJSONLogs destroys JSON logs server.
func (p *Provisioner) DestroyJSONLogs(state *State) error {
pidPath := state.GetRelativePath(jsonLogsPid)

return StopProcessByPidfile(pidPath)
}
1 change: 1 addition & 0 deletions website/content/v1.9/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ talosctl cluster create [flags]
--with-debug enable debug in Talos config to send service logs to the console
--with-firewall string inject firewall rules into the cluster, value is default policy - accept/block (QEMU only)
--with-init-node create the cluster with an init node
--with-json-logs enable JSON logs receiver and configure Talos to send logs there
--with-kubespan enable KubeSpan system
--with-network-bandwidth int specify bandwidth restriction (in kbps) on the bridge interface when creating a qemu cluster
--with-network-chaos enable to use network chaos parameters when creating a qemu cluster
Expand Down

0 comments on commit bc4c21f

Please sign in to comment.