podman logs passthrough driver support --cgroups=split

When run with --cgroups=split mode (e.g. quadlet) we do not use the a
separate cgroup for the container and just run in the unit cgroup.
When we filter logs we thus must match the unit name.
Added a small test to the quadlet test to make sure it will work.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger 2023-02-15 19:23:58 +01:00
parent d7e96536ee
commit 79a05ca2b4
No known key found for this signature in database
GPG Key ID: EB145DD938A3CAF2
4 changed files with 21 additions and 10 deletions

View File

@ -38,14 +38,14 @@ func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logCh
switch c.LogDriver() { switch c.LogDriver() {
case define.PassthroughLogging: case define.PassthroughLogging:
// if running under systemd fallback to a more native journald reading // if running under systemd fallback to a more native journald reading
if _, ok := c.config.Labels[systemdDefine.EnvVariable]; ok { if unitName, ok := c.config.Labels[systemdDefine.EnvVariable]; ok {
return c.readFromJournal(ctx, options, logChannel, colorID, true) return c.readFromJournal(ctx, options, logChannel, colorID, unitName)
} }
return fmt.Errorf("this container is using the 'passthrough' log driver, cannot read logs: %w", define.ErrNoLogs) return fmt.Errorf("this container is using the 'passthrough' log driver, cannot read logs: %w", define.ErrNoLogs)
case define.NoLogging: case define.NoLogging:
return fmt.Errorf("this container is using the 'none' log driver, cannot read logs: %w", define.ErrNoLogs) return fmt.Errorf("this container is using the 'none' log driver, cannot read logs: %w", define.ErrNoLogs)
case define.JournaldLogging: case define.JournaldLogging:
return c.readFromJournal(ctx, options, logChannel, colorID, false) return c.readFromJournal(ctx, options, logChannel, colorID, "")
case define.JSONLogging: case define.JSONLogging:
// TODO provide a separate implementation of this when Conmon // TODO provide a separate implementation of this when Conmon
// has support. // has support.

View File

@ -32,7 +32,7 @@ func init() {
} }
func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOptions, func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOptions,
logChannel chan *logs.LogLine, colorID int64, isPassthrough bool) error { logChannel chan *logs.LogLine, colorID int64, passthroughUnit string) error {
// We need the container's events in the same journal to guarantee // We need the container's events in the same journal to guarantee
// consistency, see #10323. // consistency, see #10323.
if options.Follow && c.runtime.config.Engine.EventsLogger != "journald" { if options.Follow && c.runtime.config.Engine.EventsLogger != "journald" {
@ -69,7 +69,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
return fmt.Errorf("adding filter disjunction to journald logger: %w", err) return fmt.Errorf("adding filter disjunction to journald logger: %w", err)
} }
if isPassthrough { if passthroughUnit != "" {
// Match based on systemd unit which is the container is cgroup // Match based on systemd unit which is the container is cgroup
// so we get the exact logs for a single container even in the // so we get the exact logs for a single container even in the
// play kube case where a single unit starts more than one container. // play kube case where a single unit starts more than one container.
@ -77,9 +77,16 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
if rootless.IsRootless() { if rootless.IsRootless() {
unitTypeName = "_SYSTEMD_USER_UNIT" unitTypeName = "_SYSTEMD_USER_UNIT"
} }
// FIXME: It looks like it is hardcoded to libpod-ID.scope but I am not // By default we will have our own systemd cgroup with the name libpod-<ID>.scope.
// sure were we set this with all the different cgroup modes??? value := "libpod-" + c.ID() + ".scope"
match = sdjournal.Match{Field: unitTypeName, Value: "libpod-" + c.ID() + ".scope"} if c.config.CgroupsMode == cgroupSplit {
// If cgroup split the container runs in the unit cgroup so we use this for logs,
// the good thing is we filter the podman events already out below.
// Thus we are left with the real container log and possibly podman output (e.g. logrus).
value = passthroughUnit
}
match = sdjournal.Match{Field: unitTypeName, Value: value}
if err := journal.AddMatch(match.String()); err != nil { if err := journal.AddMatch(match.String()); err != nil {
return fmt.Errorf("adding filter to journald logger: %v: %w", match, err) return fmt.Errorf("adding filter to journald logger: %v: %w", match, err)
} }

View File

@ -11,6 +11,6 @@ import (
"github.com/containers/podman/v4/libpod/logs" "github.com/containers/podman/v4/libpod/logs"
) )
func (c *Container) readFromJournal(_ context.Context, _ *logs.LogOptions, _ chan *logs.LogLine, _ int64, _ bool) error { func (c *Container) readFromJournal(_ context.Context, _ *logs.LogOptions, _ chan *logs.LogLine, _ int64, _ string) error {
return fmt.Errorf("journald logging only enabled with systemd on linux: %w", define.ErrOSNotSupported) return fmt.Errorf("journald logging only enabled with systemd on linux: %w", define.ErrOSNotSupported)
} }

View File

@ -141,7 +141,7 @@ function remove_secret() {
cat > $quadlet_file <<EOF cat > $quadlet_file <<EOF
[Container] [Container]
Image=$IMAGE Image=$IMAGE
Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; top" Exec=sh -c "echo STARTED CONTAINER; echo "READY=1" | socat -u STDIN unix-sendto:\$NOTIFY_SOCKET; sleep inf"
Notify=yes Notify=yes
EOF EOF
@ -152,6 +152,10 @@ EOF
run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME" run journalctl "--since=$STARTED_TIME" --unit="$QUADLET_SERVICE_NAME"
is "$output" '.*STARTED CONTAINER.*' is "$output" '.*STARTED CONTAINER.*'
# check that we can read the logs from the container with podman logs
run_podman logs $QUADLET_CONTAINER_NAME
assert "$output" == "STARTED CONTAINER" "podman logs works on quadlet container"
run_podman container inspect --format "{{.State.Status}}" $QUADLET_CONTAINER_NAME run_podman container inspect --format "{{.State.Status}}" $QUADLET_CONTAINER_NAME
is "$output" "running" "container should be started by systemd and hence be running" is "$output" "running" "container should be started by systemd and hence be running"