Skip to content

Commit 2894204

Browse files
authored
Merge pull request #1582 from crazy-max/k8s-exclude-namespaces
kubernetes: support negating namespaces
2 parents faa4353 + ff6d16c commit 2894204

File tree

5 files changed

+76
-44
lines changed

5 files changed

+76
-44
lines changed

docs/providers/kubernetes.md

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22

33
## About
44

5-
The Kubernetes provider allows you to analyze the pods of your Kubernetes cluster to extract images found and check
6-
for updates on the registry.
5+
The Kubernetes provider allows you to analyze the pods of your Kubernetes
6+
cluster to extract images found and check for updates on the registry.
77

88
## Quick start
99

10-
In this section we quickly go over a basic deployment using your local Kubernetes cluster.
10+
In this section, we quickly go over a basic deployment using your local
11+
Kubernetes cluster.
1112

12-
Here we use our local Kubernetes provider with a minimum configuration to analyze annotated pods (watch by default
13-
disabled).
13+
Here we use our local Kubernetes provider with a minimum configuration to
14+
analyze annotated pods (watch by default disabled).
1415

1516
Now let's create a simple pod for Diun:
1617

@@ -127,8 +128,9 @@ spec:
127128
- containerPort: 80
128129
```
129130
130-
As an example we use [nginx](https://hub.docker.com/_/nginx/) Docker image. A few [annotations](#kubernetes-annotations)
131-
are added to configure the image analysis of this pod for Diun. We can now start these 2 pods:
131+
As an example we use [nginx](https://hub.docker.com/_/nginx/) Docker image. A
132+
few [annotations](#kubernetes-annotations) are added to configure the image
133+
analysis of this pod for Diun. We can now start these 2 pods:
132134
133135
```
134136
kubectl apply -f diun.yml
@@ -176,20 +178,22 @@ The Kubernetes server endpoint as URL.
176178
!!! abstract "Environment variables"
177179
* `DIUN_PROVIDERS_KUBERNETES_ENDPOINT`
178180

179-
Kubernetes server endpoint as URL, which is only used when the behavior based on environment variables described below
180-
does not apply.
181+
Kubernetes server endpoint as URL, which is only used when the behavior based
182+
on environment variables described below does not apply.
181183

182-
When deployed into Kubernetes, Diun reads the environment variables `KUBERNETES_SERVICE_HOST` and
183-
`KUBERNETES_SERVICE_PORT` or `KUBECONFIG` to create the endpoint.
184+
When deployed into Kubernetes, Diun reads the environment variables
185+
`KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` or `KUBECONFIG` to
186+
create the endpoint.
184187

185-
The access token is looked up in `/var/run/secrets/kubernetes.io/serviceaccount/token` and the SSL CA certificate
186-
in `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`. They are both provided automatically as mounts in the
187-
pod where Diun is deployed.
188+
The access token is looked up in `/var/run/secrets/kubernetes.io/serviceaccount/token`
189+
and the SSL CA certificate in `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`.
190+
They are both provided automatically as mounts in the pod where Diun is deployed.
188191

189-
When the environment variables are not found, Diun tries to connect to the Kubernetes API server with an
190-
external-cluster client. In which case, the endpoint is required. Specifically, it may be set to the URL used
191-
by `kubectl proxy` to connect to a Kubernetes cluster using the granted authentication and authorization of the
192-
associated kubeconfig.
192+
When the environment variables are not found, Diun tries to connect to the
193+
Kubernetes API server with an external-cluster client. In which case, the
194+
endpoint is required. Specifically, it may be set to the URL used by
195+
`kubectl proxy` to connect to a Kubernetes cluster using the granted
196+
authentication and authorization of the associated kubeconfig.
193197

194198
### `token`
195199

@@ -221,7 +225,8 @@ Use content of secret file as bearer token if `token` not defined.
221225

222226
### `certAuthFilePath`
223227

224-
Path to the certificate authority file. Used for the Kubernetes client configuration.
228+
Path to the certificate authority file. Used for the Kubernetes client
229+
configuration.
225230

226231
!!! example "File"
227232
```yaml
@@ -235,7 +240,8 @@ Path to the certificate authority file. Used for the Kubernetes client configura
235240

236241
### `tlsInsecure`
237242

238-
Controls whether client does not verify the server's certificate chain and hostname (default `false`).
243+
Controls whether client does not verify the server's certificate chain and
244+
hostname (default `false`).
239245

240246
!!! example "File"
241247
```yaml
@@ -249,7 +255,9 @@ Controls whether client does not verify the server's certificate chain and hostn
249255

250256
### `namespaces`
251257

252-
Array of namespaces to watch (default all namespaces).
258+
Array of namespaces to watchBy default, it watches all namespaces. You can
259+
limit monitoring to specific namespaces by listing them. This helps reduce
260+
scope and focus on relevant pods only.
253261

254262
!!! example "File"
255263
```yaml
@@ -260,13 +268,26 @@ Array of namespaces to watch (default all namespaces).
260268
- production
261269
```
262270

271+
You can also negate namespaces by prefixing them with `!` if you want to watch
272+
all namespaces except specific ones:
273+
274+
!!! example "File"
275+
```yaml
276+
providers:
277+
kubernetes:
278+
namespaces:
279+
- !kube-system
280+
- !kube-public
281+
- !kube-node-lease
282+
```
283+
263284
!!! abstract "Environment variables"
264285
* `DIUN_PROVIDERS_KUBERNETES_NAMESPACES` (comma separated)
265286

266287
### `watchByDefault`
267288

268-
Enable watch by default. If false, pods that don't have `diun.enable: "true"` annotation will be ignored
269-
(default `false`).
289+
Enable watch by default. If false, pods that don't have `diun.enable: "true"`
290+
annotation will be ignored (default `false`).
270291

271292
!!! example "File"
272293
```yaml
@@ -280,7 +301,8 @@ Enable watch by default. If false, pods that don't have `diun.enable: "true"` an
280301

281302
## Kubernetes annotations
282303

283-
You can configure more finely the way to analyze the image of your pods through Kubernetes annotations:
304+
You can configure more finely the way to analyze the image of your pods through
305+
Kubernetes annotations:
284306

285307
| Name | Default | Description |
286308
|---------------------|--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|

internal/provider/dockerfile/image.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ package dockerfile
22

33
import (
44
"reflect"
5+
"slices"
56
"strings"
67

78
"github.com/bmatcuk/doublestar/v3"
89
"github.com/crazy-max/diun/v4/internal/model"
910
"github.com/crazy-max/diun/v4/internal/provider"
1011
"github.com/crazy-max/diun/v4/pkg/dockerfile"
11-
"github.com/crazy-max/diun/v4/pkg/utl"
1212
)
1313

1414
func (c *Client) listExtImage() (list []model.Image) {
@@ -67,7 +67,7 @@ func (c *Client) listDockerfiles(patterns []string) (dfiles []string) {
6767
continue
6868
}
6969
for _, dfile := range matches {
70-
if utl.Contains(dfiles, dfile) {
70+
if slices.Contains(dfiles, dfile) {
7171
continue
7272
}
7373
dfiles = append(dfiles, dfile)

pkg/k8s/client.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ import (
1515

1616
// Client represents an active kubernetes object
1717
type Client struct {
18-
ctx context.Context
19-
namespaces []string
20-
API *kubernetes.Clientset
18+
ctx context.Context
19+
namespaces []string
20+
namespacesExcludes []string
21+
API *kubernetes.Clientset
2122
}
2223

2324
// Options holds kubernetes client object options
@@ -47,14 +48,29 @@ func New(opts Options) (*Client, error) {
4748
api, err = newExternalClusterClient(opts)
4849
}
4950

50-
if len(opts.Namespaces) == 0 {
51-
opts.Namespaces = []string{metav1.NamespaceAll}
51+
var namespaces []string
52+
var namespacesExcluded []string
53+
for _, ns := range opts.Namespaces {
54+
if ns == "" {
55+
continue
56+
}
57+
if ns[0] == '!' {
58+
if len(ns) > 1 {
59+
namespacesExcluded = append(namespacesExcluded, ns[1:])
60+
}
61+
} else {
62+
namespaces = append(namespaces, ns)
63+
}
64+
}
65+
if len(namespaces) == 0 {
66+
namespaces = []string{metav1.NamespaceAll}
5267
}
5368

5469
return &Client{
55-
ctx: context.Background(),
56-
namespaces: opts.Namespaces,
57-
API: api,
70+
ctx: context.Background(),
71+
namespaces: namespaces,
72+
namespacesExcludes: namespacesExcluded,
73+
API: api,
5874
}, err
5975
}
6076

pkg/k8s/pod.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package k8s
22

33
import (
4+
"slices"
45
"sort"
56

67
v1 "k8s.io/api/core/v1"
@@ -17,6 +18,9 @@ func (c *Client) PodList(opts metav1.ListOptions) ([]v1.Pod, error) {
1718
return nil, err
1819
}
1920
for _, pod := range pods.Items {
21+
if slices.Contains(c.namespacesExcludes, pod.Namespace) {
22+
continue
23+
}
2024
podList = appendPod(podList, pod)
2125
}
2226
}

pkg/utl/utl.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,3 @@ func NewTrue() *bool {
8383
func NewDuration(duration time.Duration) *time.Duration {
8484
return &duration
8585
}
86-
87-
// Contains checks if a slice contains a string
88-
func Contains(s []string, e string) bool {
89-
for _, a := range s {
90-
if a == e {
91-
return true
92-
}
93-
}
94-
return false
95-
}

0 commit comments

Comments
 (0)