diff --git a/cmd/flux/logs.go b/cmd/flux/logs.go
index 6db6ef924e1061bac7e6372c80d1b7230b270032..355cdfd0c17525dd3a95ee53083a12b453c74efa 100644
--- a/cmd/flux/logs.go
+++ b/cmd/flux/logs.go
@@ -26,12 +26,14 @@ import (
 	"os"
 	"strings"
 	"sync"
+	"time"
 
 	"github.com/spf13/cobra"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
+	"k8s.io/kubectl/pkg/util"
 
 	"github.com/fluxcd/flux2/internal/flags"
 	"github.com/fluxcd/flux2/internal/utils"
@@ -42,16 +44,19 @@ var logsCmd = &cobra.Command{
 	Short: "Display formatted logs for Flux components",
 	Long:  "The logs command displays formatted logs from various Flux components.",
 	Example: `  # Print the reconciliation logs of all Flux custom resources in your cluster
-	 flux logs --all-namespaces
+  flux logs --all-namespaces
+  
+  # Print all logs of all Flux custom resources newer than 2 minutes
+  flux logs --all-namespaces --since=2m
 
-	# Stream logs for a particular log level
-	flux logs --follow --level=error --all-namespaces
+  # Stream logs for a particular log level
+  flux logs --follow --level=error --all-namespaces
 
-	# Filter logs by kind, name and namespace
-	flux logs --kind=Kustomization --name=podinfo --namespace=default
+  # Filter logs by kind, name and namespace
+  flux logs --kind=Kustomization --name=podinfo --namespace=default
 
-	# Print logs when Flux is installed in a different namespace than flux-system
-	flux logs --flux-namespace=my-namespace
+  # Print logs when Flux is installed in a different namespace than flux-system
+  flux logs --flux-namespace=my-namespace
     `,
 	RunE: logsCmdRun,
 }
@@ -64,6 +69,8 @@ type logsFlags struct {
 	name          string
 	fluxNamespace string
 	allNamespaces bool
+	sinceTime     string
+	sinceSeconds  time.Duration
 }
 
 var logsArgs = &logsFlags{
@@ -78,6 +85,8 @@ func init() {
 	logsCmd.Flags().Int64VarP(&logsArgs.tail, "tail", "", logsArgs.tail, "lines of recent log file to display")
 	logsCmd.Flags().StringVarP(&logsArgs.fluxNamespace, "flux-namespace", "", rootArgs.defaults.Namespace, "the namespace where the Flux components are running")
 	logsCmd.Flags().BoolVarP(&logsArgs.allNamespaces, "all-namespaces", "A", false, "displays logs for objects across all namespaces")
+	logsCmd.Flags().DurationVar(&logsArgs.sinceSeconds, "since", logsArgs.sinceSeconds, "Only return logs newer than a relative duration like 5s, 2m, or 3h. Defaults to all logs. Only one of since-time / since may be used.")
+	logsCmd.Flags().StringVar(&logsArgs.sinceTime, "since-time", logsArgs.sinceTime, "Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.")
 	rootCmd.AddCommand(logsCmd)
 }
 
@@ -87,7 +96,6 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
 	ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
 	defer cancel()
 
-	var pods []corev1.Pod
 	cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
 	if err != nil {
 		return err
@@ -102,7 +110,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
 		return fmt.Errorf("no argument required")
 	}
 
-	pods, err = getPods(ctx, clientset, fluxSelector)
+	pods, err := getPods(ctx, clientset, fluxSelector)
 	if err != nil {
 		return err
 	}
@@ -115,6 +123,24 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
 		logOpts.TailLines = &logsArgs.tail
 	}
 
+	if len(logsArgs.sinceTime) > 0 && logsArgs.sinceSeconds != 0 {
+		return fmt.Errorf("at most one of `sinceTime` or `sinceSeconds` may be specified")
+	}
+
+	if len(logsArgs.sinceTime) > 0 {
+		t, err := util.ParseRFC3339(logsArgs.sinceTime, metav1.Now)
+		if err != nil {
+			return fmt.Errorf("%s is not a valid (RFC3339) time", logsArgs.sinceTime)
+		}
+		logOpts.SinceTime = &t
+	}
+
+	if logsArgs.sinceSeconds != 0 {
+		// round up to the nearest second
+		sec := int64(logsArgs.sinceSeconds.Round(time.Second).Seconds())
+		logOpts.SinceSeconds = &sec
+	}
+
 	var requests []rest.ResponseWrapper
 	for _, pod := range pods {
 		req := clientset.CoreV1().Pods(logsArgs.fluxNamespace).GetLogs(pod.Name, logOpts)
diff --git a/cmd/flux/logs_test.go b/cmd/flux/logs_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..d682141038b926a1ff71e22f3d22c4f335a46b48
--- /dev/null
+++ b/cmd/flux/logs_test.go
@@ -0,0 +1,63 @@
+// +build unit
+
+package main
+
+import (
+	"testing"
+)
+
+func TestLogsNoArgs(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs",
+		assert: assertSuccess(),
+	}
+	cmd.runTestCmd(t)
+}
+
+func TestLogsAllNamespaces(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs --all-namespaces",
+		assert: assertSuccess(),
+	}
+	cmd.runTestCmd(t)
+}
+
+func TestLogsSince(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs --since=2m",
+		assert: assertSuccess(),
+	}
+	cmd.runTestCmd(t)
+}
+
+func TestLogsSinceInvalid(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs --since=XXX",
+		assert: assertError(`invalid argument "XXX" for "--since" flag: time: invalid duration "XXX"`),
+	}
+	cmd.runTestCmd(t)
+}
+
+func TestLogsSinceTime(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs --since-time=2021-08-06T14:26:25.546Z",
+		assert: assertSuccess(),
+	}
+	cmd.runTestCmd(t)
+}
+
+func TestLogsSinceTimeInvalid(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs --since-time=XXX",
+		assert: assertError("XXX is not a valid (RFC3339) time"),
+	}
+	cmd.runTestCmd(t)
+}
+
+func TestLogsSinceOnlyOneAllowed(t *testing.T) {
+	cmd := cmdTestCase{
+		args:   "logs --since=2m --since-time=2021-08-06T14:26:25.546Z",
+		assert: assertError("at most one of `sinceTime` or `sinceSeconds` may be specified"),
+	}
+	cmd.runTestCmd(t)
+}
diff --git a/go.mod b/go.mod
index 6a4540b9dfc4b4d2260ed2688ce1c248e44484ba..de43a93552b2b68665299116bc9807c635c114d3 100644
--- a/go.mod
+++ b/go.mod
@@ -30,6 +30,7 @@ require (
 	k8s.io/apiextensions-apiserver v0.21.3
 	k8s.io/apimachinery v0.21.3
 	k8s.io/client-go v0.21.3
+	k8s.io/kubectl v0.21.1
 	sigs.k8s.io/cli-utils v0.25.1-0.20210608181808-f3974341173a
 	sigs.k8s.io/controller-runtime v0.9.5
 	sigs.k8s.io/kustomize/api v0.8.10
diff --git a/go.sum b/go.sum
index b6cf5b58611f4d21c0725e1201464779dc128c77..6416ed02362d84d152dbc1e4d7c937622b39ccdd 100644
--- a/go.sum
+++ b/go.sum
@@ -1235,6 +1235,7 @@ k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C
 k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
 k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
 k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
+k8s.io/kubectl v0.21.1 h1:ySEusoeSgSDSiSBncDMsNrthSa3OSlXqT4R2rf1VFTw=
 k8s.io/kubectl v0.21.1/go.mod h1:PMYR88MqESuysBM/MX+Vu4JbX/50nY4d4kny+SPEI2U=
 k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE=
 k8s.io/metrics v0.21.1/go.mod h1:pyDVLsLe++FIGDBFU80NcW4xMFsuiVTWL8Zfi7+PpNo=