Explore all Prometheus open source software, libraries, packages, source code, cloud functions and APIs.

Popular New Releases in Prometheus

netdata

v1.34.1

grafana

8.5.0 (2022-04-21)

prometheus

2.35.0-rc1 / 2022-04-14

faas

Export new metrics for OpenFaaS Pro scaling (fixed build)

skywalking

9.0.0

Popular Libraries in Prometheus

netdata

by netdata doticoncdoticon

star image 58912 doticonGPL-3.0

Real-time performance monitoring, done right! https://www.netdata.cloud

grafana

by grafana doticontypescriptdoticon

star image 48159 doticonAGPL-3.0

The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.

prometheus

by prometheus doticongodoticon

star image 42027 doticonApache-2.0

The Prometheus monitoring system and time series database.

devops-exercises

by bregman-arie doticonpythondoticon

star image 22045 doticonNOASSERTION

Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions

faas

by openfaas doticongodoticon

star image 20981 doticonMIT

OpenFaaS - Serverless Functions Made Simple

skywalking

by apache doticonjavadoticon

star image 19150 doticonApache-2.0

APM, Application Performance Monitoring System

cat

by dianping doticonjavadoticon

star image 16597 doticonApache-2.0

CAT 作为服务端项目基础组件,提供了 Java, C/C++, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等,消息队列,配置系统等)深度集成,为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。

loki

by grafana doticongodoticon

star image 15577 doticonAGPL-3.0

Like Prometheus, but for logs.

zipkin

by openzipkin doticonjavadoticon

star image 15220 doticonApache-2.0

Zipkin is a distributed tracing system

Trending New libraries in Prometheus

signoz

by SigNoz doticontypescriptdoticon

star image 6127 doticonMIT

SigNoz is an open-source APM. It helps developers monitor their applications & troubleshoot problems, an open-source alternative to DataDog, NewRelic, etc. 🔥 🖥. 👉 Open source Application Performance Monitoring (APM) & Observability tool

nightingale

by didi doticongodoticon

star image 4433 doticonApache-2.0

An enterprise-level cloud-native monitoring system, which can be used as drop-in replacement of Prometheus for alerting and management.

jupiter

by douyu doticongodoticon

star image 3691 doticonApache-2.0

Jupiter是斗鱼开源的面向服务治理的Golang微服务框架

CBL-Mariner

by microsoft doticongodoticon

star image 3213 doticonMIT

Linux OS for Azure 1P services and edge appliances

erda

by erda-project doticongodoticon

star image 2294 doticonApache-2.0

An enterprise-grade Cloud-Native application platform for Kubernetes.

tempo

by grafana doticongodoticon

star image 1958 doticonAGPL-3.0

Grafana Tempo is a high volume, minimal dependency distributed tracing backend.

Prometheus-Basics

by yolossn doticongodoticon

star image 1505 doticonMIT

A beginner friendly introduction to prometheus 🔥

sloth

by slok doticongodoticon

star image 1033 doticonApache-2.0

🦥 Easy and simple Prometheus SLO (service level objectives) generator

opstrace

by opstrace doticontypescriptdoticon

star image 1012 doticonApache-2.0

The Open Source Observability Distribution

Top Authors in Prometheus

1

sensu-plugins

42 Libraries

star icon466

2

prometheus

25 Libraries

star icon71434

3

grafana

25 Libraries

star icon67872

4

percona

19 Libraries

star icon3930

5

microsoft

18 Libraries

star icon5062

6

sematext

15 Libraries

star icon356

7

prom-client-net

15 Libraries

star icon296

8

sapcc

14 Libraries

star icon180

9

rancher

13 Libraries

star icon624

10

google

11 Libraries

star icon5124

1

42 Libraries

star icon466

2

25 Libraries

star icon71434

3

25 Libraries

star icon67872

4

19 Libraries

star icon3930

5

18 Libraries

star icon5062

6

15 Libraries

star icon356

7

15 Libraries

star icon296

8

14 Libraries

star icon180

9

13 Libraries

star icon624

10

11 Libraries

star icon5124

Trending Kits in Prometheus

No Trending Kits are available at this moment for Prometheus

Trending Discussions on Prometheus

Enable use of images from the local library on Kubernetes

Add Kubernetes scrape target to Prometheus instance that is NOT in Kubernetes

Prometheus cannot scrape from spring-boot application over HTTPS

Apply yaml file using k8s SDK

Content of go.sum and modules really used by a go application

Is Google Managed Prometheus billing per million or per billion?

Filter the parts of a Request Path which match against a Static Segment in Servant

Can't deploy streamlit app on share.streamlit.io

OAUTH2 user service with Custom Authentication Providers

Prometheus kubelet metrics with pod labels

QUESTION

Enable use of images from the local library on Kubernetes

Asked 2022-Mar-20 at 13:23

I'm following a tutorial https://docs.openfaas.com/tutorials/first-python-function/,

currently, I have the right image

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9

there is a step that forewarns me to do some setup(My case is I'm using Kubernetes and minikube and don't want to push to a remote container registry, I should enable the use of images from the local library on Kubernetes.), I see the hints

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10

I'm not sure how to configure it correctly. the final result indicates I failed.

Unsurprisingly, I couldn't access the function service, I find some clues in https://docs.openfaas.com/deployment/troubleshooting/#openfaas-didnt-start which might help to diagnose the problem.

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50

hello-openfaas.yml

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50version: 1.0
51provider:
52  name: openfaas
53  gateway: http://IP:8099
54functions:
55  hello-openfaas:
56    lang: python3
57    handler: ./hello-openfaas
58    image: wm/hello-openfaas:latest
59    imagePullPolicy: Never
60

I create a new project hello-openfaas2 to reproduce this error

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50version: 1.0
51provider:
52  name: openfaas
53  gateway: http://IP:8099
54functions:
55  hello-openfaas:
56    lang: python3
57    handler: ./hello-openfaas
58    image: wm/hello-openfaas:latest
59    imagePullPolicy: Never
60$ faas-cli new --lang python3 hello-openfaas2 --prefix="wm"
61Folder: hello-openfaas2 created.
62# I add `imagePullPolicy: Never` to `hello-openfaas2.yml`
63$ faas-cli build -f ./hello-openfaas2.yml 
64$ faas-cli deploy -f ./hello-openfaas2.yml 
65Deploying: hello-openfaas2.
66WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
67
68Deployed. 202 Accepted.
69URL: http://192.168.1.3:8099/function/hello-openfaas2
70
71
72$ kubectl logs -n openfaas-fn deploy/hello-openfaas2
73Error from server (BadRequest): container "hello-openfaas2" in pod "hello-openfaas2-7c67488865-7d7vm" is waiting to start: image can't be pulled
74
75$ kubectl get pods --all-namespaces
76NAMESPACE              NAME                                        READY   STATUS             RESTARTS         AGE
77kube-system            coredns-64897985d-kp7vf                     1/1     Running            0                47h
78...
79openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0                4h28m
80openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0                18h
81openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0                127m
82openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0                165m
83openfaas-fn            hello-openfaas2-7c67488865-qmrkl            0/1     ImagePullBackOff   0                13m
84openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0                97m
85openfaas-fn            hello-python-554b464498-zxcdv               0/1     ErrImagePull       0                3h23m
86openfaas-fn            hello-python-8698bc68bd-62gh9               0/1     ImagePullBackOff   0                3h25m
87

from https://docs.openfaas.com/reference/yaml/, I know I put the imagePullPolicy in the wrong place, there is no such keyword in its schema.

I also tried eval $(minikube docker-env and still get the same error.


I've a feeling that faas-cli deploy can be replace by helm, they all mean to run the image(whether from remote or local) in Kubernetes cluster, then I can use helm chart to setup the pullPolicy there. Even though the detail is not still clear to me, This discovery inspires me.


So far, after eval $(minikube docker-env)

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50version: 1.0
51provider:
52  name: openfaas
53  gateway: http://IP:8099
54functions:
55  hello-openfaas:
56    lang: python3
57    handler: ./hello-openfaas
58    image: wm/hello-openfaas:latest
59    imagePullPolicy: Never
60$ faas-cli new --lang python3 hello-openfaas2 --prefix="wm"
61Folder: hello-openfaas2 created.
62# I add `imagePullPolicy: Never` to `hello-openfaas2.yml`
63$ faas-cli build -f ./hello-openfaas2.yml 
64$ faas-cli deploy -f ./hello-openfaas2.yml 
65Deploying: hello-openfaas2.
66WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
67
68Deployed. 202 Accepted.
69URL: http://192.168.1.3:8099/function/hello-openfaas2
70
71
72$ kubectl logs -n openfaas-fn deploy/hello-openfaas2
73Error from server (BadRequest): container "hello-openfaas2" in pod "hello-openfaas2-7c67488865-7d7vm" is waiting to start: image can't be pulled
74
75$ kubectl get pods --all-namespaces
76NAMESPACE              NAME                                        READY   STATUS             RESTARTS         AGE
77kube-system            coredns-64897985d-kp7vf                     1/1     Running            0                47h
78...
79openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0                4h28m
80openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0                18h
81openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0                127m
82openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0                165m
83openfaas-fn            hello-openfaas2-7c67488865-qmrkl            0/1     ImagePullBackOff   0                13m
84openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0                97m
85openfaas-fn            hello-python-554b464498-zxcdv               0/1     ErrImagePull       0                3h23m
86openfaas-fn            hello-python-8698bc68bd-62gh9               0/1     ImagePullBackOff   0                3h25m
87$ docker images
88REPOSITORY                                TAG        IMAGE ID       CREATED             SIZE
89wm/hello-openfaas2                        0.1        03c21bd96d5e   About an hour ago   65.2MB
90python                                    3-alpine   69fba17b9bae   12 days ago         48.6MB
91ghcr.io/openfaas/figlet                   latest     ca5eef0de441   2 weeks ago         14.8MB
92ghcr.io/openfaas/alpine                   latest     35f3d4be6bb8   2 weeks ago         14.2MB
93ghcr.io/openfaas/faas-netes               0.14.2     524b510505ec   3 weeks ago         77.3MB
94k8s.gcr.io/kube-apiserver                 v1.23.3    f40be0088a83   7 weeks ago         135MB
95k8s.gcr.io/kube-controller-manager        v1.23.3    b07520cd7ab7   7 weeks ago         125MB
96k8s.gcr.io/kube-scheduler                 v1.23.3    99a3486be4f2   7 weeks ago         53.5MB
97k8s.gcr.io/kube-proxy                     v1.23.3    9b7cc9982109   7 weeks ago         112MB
98ghcr.io/openfaas/gateway                  0.21.3     ab4851262cd1   7 weeks ago         30.6MB
99ghcr.io/openfaas/basic-auth               0.21.3     16e7168a17a3   7 weeks ago         14.3MB
100k8s.gcr.io/etcd                           3.5.1-0    25f8c7f3da61   4 months ago        293MB
101ghcr.io/openfaas/classic-watchdog         0.2.0      6f97aa96da81   4 months ago        8.18MB
102k8s.gcr.io/coredns/coredns                v1.8.6     a4ca41631cc7   5 months ago        46.8MB
103k8s.gcr.io/pause                          3.6        6270bb605e12   6 months ago        683kB
104ghcr.io/openfaas/queue-worker             0.12.2     56e7216201bc   7 months ago        7.97MB
105kubernetesui/dashboard                    v2.3.1     e1482a24335a   9 months ago        220MB
106kubernetesui/metrics-scraper              v1.0.7     7801cfc6d5c0   9 months ago        34.4MB
107nats-streaming                            0.22.0     12f2d32e0c9a   9 months ago        19.8MB
108gcr.io/k8s-minikube/storage-provisioner   v5         6e38f40d628d   11 months ago       31.5MB
109functions/markdown-render                 latest     93b5da182216   2 years ago         24.6MB
110functions/hubstats                        latest     01affa91e9e4   2 years ago         29.3MB
111functions/nodeinfo                        latest     2fe8a87bf79c   2 years ago         71.4MB
112functions/alpine                          latest     46c6f6d74471   2 years ago         21.5MB
113prom/prometheus                           v2.11.0    b97ed892eb23   2 years ago         126MB
114prom/alertmanager                         v0.18.0    ce3c87f17369   2 years ago         51.9MB
115alexellis2/openfaas-colorization          0.4.1      d36b67b1b5c1   2 years ago         1.84GB
116rorpage/text-to-speech                    latest     5dc20810eb54   2 years ago         86.9MB
117stefanprodan/faas-grafana                 4.6.3      2a4bd9caea50   4 years ago         284MB
118
119$ kubectl get pods --all-namespaces
120NAMESPACE              NAME                                        READY   STATUS             RESTARTS        AGE
121kube-system            coredns-64897985d-kp7vf                     1/1     Running            0               6d
122kube-system            etcd-minikube                               1/1     Running            0               6d
123kube-system            kube-apiserver-minikube                     1/1     Running            0               6d
124kube-system            kube-controller-manager-minikube            1/1     Running            0               6d
125kube-system            kube-proxy-5m8lr                            1/1     Running            0               6d
126kube-system            kube-scheduler-minikube                     1/1     Running            0               6d
127kube-system            storage-provisioner                         1/1     Running            1 (6d ago)      6d
128kubernetes-dashboard   dashboard-metrics-scraper-58549894f-97tsv   1/1     Running            0               5d7h
129kubernetes-dashboard   kubernetes-dashboard-ccd587f44-lkwcx        1/1     Running            0               5d7h
130openfaas-fn            base64-6bdbcdb64c-djz8f                     1/1     Running            0               5d1h
131openfaas-fn            colorise-85c74c686b-2fz66                   1/1     Running            0               4d5h
132openfaas-fn            echoit-5d7df6684c-k6ljn                     1/1     Running            0               5d1h
133openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0               4d5h
134openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0               4d19h
135openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0               4d3h
136openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0               4d3h
137openfaas-fn            hello-openfaas2-5c6f6cb5d9-24hkz            0/1     ImagePullBackOff   0               9m22s
138openfaas-fn            hello-openfaas2-8957bb47b-7cgjg             0/1     ImagePullBackOff   0               2d22h
139openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0               4d2h
140openfaas-fn            hello-python-6d6976845f-cwsln               0/1     ImagePullBackOff   0               3d19h
141openfaas-fn            hello-python-b577cb8dc-64wf5                0/1     ImagePullBackOff   0               3d9h
142openfaas-fn            hubstats-b6cd4dccc-z8tvl                    1/1     Running            0               5d1h
143openfaas-fn            markdown-68f69f47c8-w5m47                   1/1     Running            0               5d1h
144openfaas-fn            nodeinfo-d48cbbfcc-hfj79                    1/1     Running            0               5d1h
145openfaas-fn            openfaas2-fun                               1/1     Running            0               15s
146openfaas-fn            text-to-speech-74ffcdfd7-997t4              0/1     CrashLoopBackOff   2235 (3s ago)   4d5h
147openfaas-fn            wordcount-6489865566-cvfzr                  1/1     Running            0               5d1h
148openfaas               alertmanager-88449c789-fq2rg                1/1     Running            0               3d1h
149openfaas               basic-auth-plugin-75fd7d69c5-zw4jh          1/1     Running            0               3d2h
150openfaas               gateway-5c4bb7c5d7-n8h27                    2/2     Running            0               3d2h
151openfaas               grafana                                     1/1     Running            0               4d8h
152openfaas               nats-647b476664-hkr7p                       1/1     Running            0               3d2h
153openfaas               prometheus-687648749f-tl8jp                 1/1     Running            0               3d1h
154openfaas               queue-worker-7777ffd7f6-htx6t               1/1     Running            0               3d2h
155
156
157$ kubectl get -o yaml -n openfaas-fn deploy/hello-openfaas2
158apiVersion: apps/v1
159kind: Deployment
160metadata:
161  annotations:
162    deployment.kubernetes.io/revision: "6"
163    prometheus.io.scrape: "false"
164  creationTimestamp: "2022-03-17T12:47:35Z"
165  generation: 6
166  labels:
167    faas_function: hello-openfaas2
168  name: hello-openfaas2
169  namespace: openfaas-fn
170  resourceVersion: "400833"
171  uid: 9c4e9d26-23af-4f93-8538-4e2d96f0d7e0
172spec:
173  progressDeadlineSeconds: 600
174  replicas: 1
175  revisionHistoryLimit: 10
176  selector:
177    matchLabels:
178      faas_function: hello-openfaas2
179  strategy:
180    rollingUpdate:
181      maxSurge: 1
182      maxUnavailable: 0
183    type: RollingUpdate
184  template:
185    metadata:
186      annotations:
187        prometheus.io.scrape: "false"
188      creationTimestamp: null
189      labels:
190        faas_function: hello-openfaas2
191        uid: "969512830"
192      name: hello-openfaas2
193    spec:
194      containers:
195      - env:
196        - name: fprocess
197          value: python3 index.py
198        image: wm/hello-openfaas2:0.1
199        imagePullPolicy: Always
200        livenessProbe:
201          failureThreshold: 3
202          httpGet:
203            path: /_/health
204            port: 8080
205            scheme: HTTP
206          initialDelaySeconds: 2
207          periodSeconds: 2
208          successThreshold: 1
209          timeoutSeconds: 1
210        name: hello-openfaas2
211        ports:
212        - containerPort: 8080
213          name: http
214          protocol: TCP
215        readinessProbe:
216          failureThreshold: 3
217          httpGet:
218            path: /_/health
219            port: 8080
220            scheme: HTTP
221          initialDelaySeconds: 2
222          periodSeconds: 2
223          successThreshold: 1
224          timeoutSeconds: 1
225        resources: {}
226        securityContext:
227          allowPrivilegeEscalation: false
228          readOnlyRootFilesystem: false
229        terminationMessagePath: /dev/termination-log
230        terminationMessagePolicy: File
231      dnsPolicy: ClusterFirst
232      enableServiceLinks: false
233      restartPolicy: Always
234      schedulerName: default-scheduler
235      securityContext: {}
236      terminationGracePeriodSeconds: 30
237status:
238  conditions:
239  - lastTransitionTime: "2022-03-17T12:47:35Z"
240    lastUpdateTime: "2022-03-17T12:47:35Z"
241    message: Deployment does not have minimum availability.
242    reason: MinimumReplicasUnavailable
243    status: "False"
244    type: Available
245  - lastTransitionTime: "2022-03-20T12:16:56Z"
246    lastUpdateTime: "2022-03-20T12:16:56Z"
247    message: ReplicaSet "hello-openfaas2-5d6c7c7fb4" has timed out progressing.
248    reason: ProgressDeadlineExceeded
249    status: "False"
250    type: Progressing
251  observedGeneration: 6
252  replicas: 2
253  unavailableReplicas: 2
254  updatedReplicas: 1
255

In one shell,

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50version: 1.0
51provider:
52  name: openfaas
53  gateway: http://IP:8099
54functions:
55  hello-openfaas:
56    lang: python3
57    handler: ./hello-openfaas
58    image: wm/hello-openfaas:latest
59    imagePullPolicy: Never
60$ faas-cli new --lang python3 hello-openfaas2 --prefix="wm"
61Folder: hello-openfaas2 created.
62# I add `imagePullPolicy: Never` to `hello-openfaas2.yml`
63$ faas-cli build -f ./hello-openfaas2.yml 
64$ faas-cli deploy -f ./hello-openfaas2.yml 
65Deploying: hello-openfaas2.
66WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
67
68Deployed. 202 Accepted.
69URL: http://192.168.1.3:8099/function/hello-openfaas2
70
71
72$ kubectl logs -n openfaas-fn deploy/hello-openfaas2
73Error from server (BadRequest): container "hello-openfaas2" in pod "hello-openfaas2-7c67488865-7d7vm" is waiting to start: image can't be pulled
74
75$ kubectl get pods --all-namespaces
76NAMESPACE              NAME                                        READY   STATUS             RESTARTS         AGE
77kube-system            coredns-64897985d-kp7vf                     1/1     Running            0                47h
78...
79openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0                4h28m
80openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0                18h
81openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0                127m
82openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0                165m
83openfaas-fn            hello-openfaas2-7c67488865-qmrkl            0/1     ImagePullBackOff   0                13m
84openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0                97m
85openfaas-fn            hello-python-554b464498-zxcdv               0/1     ErrImagePull       0                3h23m
86openfaas-fn            hello-python-8698bc68bd-62gh9               0/1     ImagePullBackOff   0                3h25m
87$ docker images
88REPOSITORY                                TAG        IMAGE ID       CREATED             SIZE
89wm/hello-openfaas2                        0.1        03c21bd96d5e   About an hour ago   65.2MB
90python                                    3-alpine   69fba17b9bae   12 days ago         48.6MB
91ghcr.io/openfaas/figlet                   latest     ca5eef0de441   2 weeks ago         14.8MB
92ghcr.io/openfaas/alpine                   latest     35f3d4be6bb8   2 weeks ago         14.2MB
93ghcr.io/openfaas/faas-netes               0.14.2     524b510505ec   3 weeks ago         77.3MB
94k8s.gcr.io/kube-apiserver                 v1.23.3    f40be0088a83   7 weeks ago         135MB
95k8s.gcr.io/kube-controller-manager        v1.23.3    b07520cd7ab7   7 weeks ago         125MB
96k8s.gcr.io/kube-scheduler                 v1.23.3    99a3486be4f2   7 weeks ago         53.5MB
97k8s.gcr.io/kube-proxy                     v1.23.3    9b7cc9982109   7 weeks ago         112MB
98ghcr.io/openfaas/gateway                  0.21.3     ab4851262cd1   7 weeks ago         30.6MB
99ghcr.io/openfaas/basic-auth               0.21.3     16e7168a17a3   7 weeks ago         14.3MB
100k8s.gcr.io/etcd                           3.5.1-0    25f8c7f3da61   4 months ago        293MB
101ghcr.io/openfaas/classic-watchdog         0.2.0      6f97aa96da81   4 months ago        8.18MB
102k8s.gcr.io/coredns/coredns                v1.8.6     a4ca41631cc7   5 months ago        46.8MB
103k8s.gcr.io/pause                          3.6        6270bb605e12   6 months ago        683kB
104ghcr.io/openfaas/queue-worker             0.12.2     56e7216201bc   7 months ago        7.97MB
105kubernetesui/dashboard                    v2.3.1     e1482a24335a   9 months ago        220MB
106kubernetesui/metrics-scraper              v1.0.7     7801cfc6d5c0   9 months ago        34.4MB
107nats-streaming                            0.22.0     12f2d32e0c9a   9 months ago        19.8MB
108gcr.io/k8s-minikube/storage-provisioner   v5         6e38f40d628d   11 months ago       31.5MB
109functions/markdown-render                 latest     93b5da182216   2 years ago         24.6MB
110functions/hubstats                        latest     01affa91e9e4   2 years ago         29.3MB
111functions/nodeinfo                        latest     2fe8a87bf79c   2 years ago         71.4MB
112functions/alpine                          latest     46c6f6d74471   2 years ago         21.5MB
113prom/prometheus                           v2.11.0    b97ed892eb23   2 years ago         126MB
114prom/alertmanager                         v0.18.0    ce3c87f17369   2 years ago         51.9MB
115alexellis2/openfaas-colorization          0.4.1      d36b67b1b5c1   2 years ago         1.84GB
116rorpage/text-to-speech                    latest     5dc20810eb54   2 years ago         86.9MB
117stefanprodan/faas-grafana                 4.6.3      2a4bd9caea50   4 years ago         284MB
118
119$ kubectl get pods --all-namespaces
120NAMESPACE              NAME                                        READY   STATUS             RESTARTS        AGE
121kube-system            coredns-64897985d-kp7vf                     1/1     Running            0               6d
122kube-system            etcd-minikube                               1/1     Running            0               6d
123kube-system            kube-apiserver-minikube                     1/1     Running            0               6d
124kube-system            kube-controller-manager-minikube            1/1     Running            0               6d
125kube-system            kube-proxy-5m8lr                            1/1     Running            0               6d
126kube-system            kube-scheduler-minikube                     1/1     Running            0               6d
127kube-system            storage-provisioner                         1/1     Running            1 (6d ago)      6d
128kubernetes-dashboard   dashboard-metrics-scraper-58549894f-97tsv   1/1     Running            0               5d7h
129kubernetes-dashboard   kubernetes-dashboard-ccd587f44-lkwcx        1/1     Running            0               5d7h
130openfaas-fn            base64-6bdbcdb64c-djz8f                     1/1     Running            0               5d1h
131openfaas-fn            colorise-85c74c686b-2fz66                   1/1     Running            0               4d5h
132openfaas-fn            echoit-5d7df6684c-k6ljn                     1/1     Running            0               5d1h
133openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0               4d5h
134openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0               4d19h
135openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0               4d3h
136openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0               4d3h
137openfaas-fn            hello-openfaas2-5c6f6cb5d9-24hkz            0/1     ImagePullBackOff   0               9m22s
138openfaas-fn            hello-openfaas2-8957bb47b-7cgjg             0/1     ImagePullBackOff   0               2d22h
139openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0               4d2h
140openfaas-fn            hello-python-6d6976845f-cwsln               0/1     ImagePullBackOff   0               3d19h
141openfaas-fn            hello-python-b577cb8dc-64wf5                0/1     ImagePullBackOff   0               3d9h
142openfaas-fn            hubstats-b6cd4dccc-z8tvl                    1/1     Running            0               5d1h
143openfaas-fn            markdown-68f69f47c8-w5m47                   1/1     Running            0               5d1h
144openfaas-fn            nodeinfo-d48cbbfcc-hfj79                    1/1     Running            0               5d1h
145openfaas-fn            openfaas2-fun                               1/1     Running            0               15s
146openfaas-fn            text-to-speech-74ffcdfd7-997t4              0/1     CrashLoopBackOff   2235 (3s ago)   4d5h
147openfaas-fn            wordcount-6489865566-cvfzr                  1/1     Running            0               5d1h
148openfaas               alertmanager-88449c789-fq2rg                1/1     Running            0               3d1h
149openfaas               basic-auth-plugin-75fd7d69c5-zw4jh          1/1     Running            0               3d2h
150openfaas               gateway-5c4bb7c5d7-n8h27                    2/2     Running            0               3d2h
151openfaas               grafana                                     1/1     Running            0               4d8h
152openfaas               nats-647b476664-hkr7p                       1/1     Running            0               3d2h
153openfaas               prometheus-687648749f-tl8jp                 1/1     Running            0               3d1h
154openfaas               queue-worker-7777ffd7f6-htx6t               1/1     Running            0               3d2h
155
156
157$ kubectl get -o yaml -n openfaas-fn deploy/hello-openfaas2
158apiVersion: apps/v1
159kind: Deployment
160metadata:
161  annotations:
162    deployment.kubernetes.io/revision: "6"
163    prometheus.io.scrape: "false"
164  creationTimestamp: "2022-03-17T12:47:35Z"
165  generation: 6
166  labels:
167    faas_function: hello-openfaas2
168  name: hello-openfaas2
169  namespace: openfaas-fn
170  resourceVersion: "400833"
171  uid: 9c4e9d26-23af-4f93-8538-4e2d96f0d7e0
172spec:
173  progressDeadlineSeconds: 600
174  replicas: 1
175  revisionHistoryLimit: 10
176  selector:
177    matchLabels:
178      faas_function: hello-openfaas2
179  strategy:
180    rollingUpdate:
181      maxSurge: 1
182      maxUnavailable: 0
183    type: RollingUpdate
184  template:
185    metadata:
186      annotations:
187        prometheus.io.scrape: "false"
188      creationTimestamp: null
189      labels:
190        faas_function: hello-openfaas2
191        uid: "969512830"
192      name: hello-openfaas2
193    spec:
194      containers:
195      - env:
196        - name: fprocess
197          value: python3 index.py
198        image: wm/hello-openfaas2:0.1
199        imagePullPolicy: Always
200        livenessProbe:
201          failureThreshold: 3
202          httpGet:
203            path: /_/health
204            port: 8080
205            scheme: HTTP
206          initialDelaySeconds: 2
207          periodSeconds: 2
208          successThreshold: 1
209          timeoutSeconds: 1
210        name: hello-openfaas2
211        ports:
212        - containerPort: 8080
213          name: http
214          protocol: TCP
215        readinessProbe:
216          failureThreshold: 3
217          httpGet:
218            path: /_/health
219            port: 8080
220            scheme: HTTP
221          initialDelaySeconds: 2
222          periodSeconds: 2
223          successThreshold: 1
224          timeoutSeconds: 1
225        resources: {}
226        securityContext:
227          allowPrivilegeEscalation: false
228          readOnlyRootFilesystem: false
229        terminationMessagePath: /dev/termination-log
230        terminationMessagePolicy: File
231      dnsPolicy: ClusterFirst
232      enableServiceLinks: false
233      restartPolicy: Always
234      schedulerName: default-scheduler
235      securityContext: {}
236      terminationGracePeriodSeconds: 30
237status:
238  conditions:
239  - lastTransitionTime: "2022-03-17T12:47:35Z"
240    lastUpdateTime: "2022-03-17T12:47:35Z"
241    message: Deployment does not have minimum availability.
242    reason: MinimumReplicasUnavailable
243    status: "False"
244    type: Available
245  - lastTransitionTime: "2022-03-20T12:16:56Z"
246    lastUpdateTime: "2022-03-20T12:16:56Z"
247    message: ReplicaSet "hello-openfaas2-5d6c7c7fb4" has timed out progressing.
248    reason: ProgressDeadlineExceeded
249    status: "False"
250    type: Progressing
251  observedGeneration: 6
252  replicas: 2
253  unavailableReplicas: 2
254  updatedReplicas: 1
255docker@minikube:~$ docker run  --name wm -ti wm/hello-openfaas2:0.1
2562022/03/20 13:04:52 Version: 0.2.0  SHA: 56bf6aac54deb3863a690f5fc03a2a38e7d9e6ef
2572022/03/20 13:04:52 Timeouts: read: 5s write: 5s hard: 0s health: 5s.
2582022/03/20 13:04:52 Listening on port: 8080
259...
260
261

and another shell

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50version: 1.0
51provider:
52  name: openfaas
53  gateway: http://IP:8099
54functions:
55  hello-openfaas:
56    lang: python3
57    handler: ./hello-openfaas
58    image: wm/hello-openfaas:latest
59    imagePullPolicy: Never
60$ faas-cli new --lang python3 hello-openfaas2 --prefix="wm"
61Folder: hello-openfaas2 created.
62# I add `imagePullPolicy: Never` to `hello-openfaas2.yml`
63$ faas-cli build -f ./hello-openfaas2.yml 
64$ faas-cli deploy -f ./hello-openfaas2.yml 
65Deploying: hello-openfaas2.
66WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
67
68Deployed. 202 Accepted.
69URL: http://192.168.1.3:8099/function/hello-openfaas2
70
71
72$ kubectl logs -n openfaas-fn deploy/hello-openfaas2
73Error from server (BadRequest): container "hello-openfaas2" in pod "hello-openfaas2-7c67488865-7d7vm" is waiting to start: image can't be pulled
74
75$ kubectl get pods --all-namespaces
76NAMESPACE              NAME                                        READY   STATUS             RESTARTS         AGE
77kube-system            coredns-64897985d-kp7vf                     1/1     Running            0                47h
78...
79openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0                4h28m
80openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0                18h
81openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0                127m
82openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0                165m
83openfaas-fn            hello-openfaas2-7c67488865-qmrkl            0/1     ImagePullBackOff   0                13m
84openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0                97m
85openfaas-fn            hello-python-554b464498-zxcdv               0/1     ErrImagePull       0                3h23m
86openfaas-fn            hello-python-8698bc68bd-62gh9               0/1     ImagePullBackOff   0                3h25m
87$ docker images
88REPOSITORY                                TAG        IMAGE ID       CREATED             SIZE
89wm/hello-openfaas2                        0.1        03c21bd96d5e   About an hour ago   65.2MB
90python                                    3-alpine   69fba17b9bae   12 days ago         48.6MB
91ghcr.io/openfaas/figlet                   latest     ca5eef0de441   2 weeks ago         14.8MB
92ghcr.io/openfaas/alpine                   latest     35f3d4be6bb8   2 weeks ago         14.2MB
93ghcr.io/openfaas/faas-netes               0.14.2     524b510505ec   3 weeks ago         77.3MB
94k8s.gcr.io/kube-apiserver                 v1.23.3    f40be0088a83   7 weeks ago         135MB
95k8s.gcr.io/kube-controller-manager        v1.23.3    b07520cd7ab7   7 weeks ago         125MB
96k8s.gcr.io/kube-scheduler                 v1.23.3    99a3486be4f2   7 weeks ago         53.5MB
97k8s.gcr.io/kube-proxy                     v1.23.3    9b7cc9982109   7 weeks ago         112MB
98ghcr.io/openfaas/gateway                  0.21.3     ab4851262cd1   7 weeks ago         30.6MB
99ghcr.io/openfaas/basic-auth               0.21.3     16e7168a17a3   7 weeks ago         14.3MB
100k8s.gcr.io/etcd                           3.5.1-0    25f8c7f3da61   4 months ago        293MB
101ghcr.io/openfaas/classic-watchdog         0.2.0      6f97aa96da81   4 months ago        8.18MB
102k8s.gcr.io/coredns/coredns                v1.8.6     a4ca41631cc7   5 months ago        46.8MB
103k8s.gcr.io/pause                          3.6        6270bb605e12   6 months ago        683kB
104ghcr.io/openfaas/queue-worker             0.12.2     56e7216201bc   7 months ago        7.97MB
105kubernetesui/dashboard                    v2.3.1     e1482a24335a   9 months ago        220MB
106kubernetesui/metrics-scraper              v1.0.7     7801cfc6d5c0   9 months ago        34.4MB
107nats-streaming                            0.22.0     12f2d32e0c9a   9 months ago        19.8MB
108gcr.io/k8s-minikube/storage-provisioner   v5         6e38f40d628d   11 months ago       31.5MB
109functions/markdown-render                 latest     93b5da182216   2 years ago         24.6MB
110functions/hubstats                        latest     01affa91e9e4   2 years ago         29.3MB
111functions/nodeinfo                        latest     2fe8a87bf79c   2 years ago         71.4MB
112functions/alpine                          latest     46c6f6d74471   2 years ago         21.5MB
113prom/prometheus                           v2.11.0    b97ed892eb23   2 years ago         126MB
114prom/alertmanager                         v0.18.0    ce3c87f17369   2 years ago         51.9MB
115alexellis2/openfaas-colorization          0.4.1      d36b67b1b5c1   2 years ago         1.84GB
116rorpage/text-to-speech                    latest     5dc20810eb54   2 years ago         86.9MB
117stefanprodan/faas-grafana                 4.6.3      2a4bd9caea50   4 years ago         284MB
118
119$ kubectl get pods --all-namespaces
120NAMESPACE              NAME                                        READY   STATUS             RESTARTS        AGE
121kube-system            coredns-64897985d-kp7vf                     1/1     Running            0               6d
122kube-system            etcd-minikube                               1/1     Running            0               6d
123kube-system            kube-apiserver-minikube                     1/1     Running            0               6d
124kube-system            kube-controller-manager-minikube            1/1     Running            0               6d
125kube-system            kube-proxy-5m8lr                            1/1     Running            0               6d
126kube-system            kube-scheduler-minikube                     1/1     Running            0               6d
127kube-system            storage-provisioner                         1/1     Running            1 (6d ago)      6d
128kubernetes-dashboard   dashboard-metrics-scraper-58549894f-97tsv   1/1     Running            0               5d7h
129kubernetes-dashboard   kubernetes-dashboard-ccd587f44-lkwcx        1/1     Running            0               5d7h
130openfaas-fn            base64-6bdbcdb64c-djz8f                     1/1     Running            0               5d1h
131openfaas-fn            colorise-85c74c686b-2fz66                   1/1     Running            0               4d5h
132openfaas-fn            echoit-5d7df6684c-k6ljn                     1/1     Running            0               5d1h
133openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0               4d5h
134openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0               4d19h
135openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0               4d3h
136openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0               4d3h
137openfaas-fn            hello-openfaas2-5c6f6cb5d9-24hkz            0/1     ImagePullBackOff   0               9m22s
138openfaas-fn            hello-openfaas2-8957bb47b-7cgjg             0/1     ImagePullBackOff   0               2d22h
139openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0               4d2h
140openfaas-fn            hello-python-6d6976845f-cwsln               0/1     ImagePullBackOff   0               3d19h
141openfaas-fn            hello-python-b577cb8dc-64wf5                0/1     ImagePullBackOff   0               3d9h
142openfaas-fn            hubstats-b6cd4dccc-z8tvl                    1/1     Running            0               5d1h
143openfaas-fn            markdown-68f69f47c8-w5m47                   1/1     Running            0               5d1h
144openfaas-fn            nodeinfo-d48cbbfcc-hfj79                    1/1     Running            0               5d1h
145openfaas-fn            openfaas2-fun                               1/1     Running            0               15s
146openfaas-fn            text-to-speech-74ffcdfd7-997t4              0/1     CrashLoopBackOff   2235 (3s ago)   4d5h
147openfaas-fn            wordcount-6489865566-cvfzr                  1/1     Running            0               5d1h
148openfaas               alertmanager-88449c789-fq2rg                1/1     Running            0               3d1h
149openfaas               basic-auth-plugin-75fd7d69c5-zw4jh          1/1     Running            0               3d2h
150openfaas               gateway-5c4bb7c5d7-n8h27                    2/2     Running            0               3d2h
151openfaas               grafana                                     1/1     Running            0               4d8h
152openfaas               nats-647b476664-hkr7p                       1/1     Running            0               3d2h
153openfaas               prometheus-687648749f-tl8jp                 1/1     Running            0               3d1h
154openfaas               queue-worker-7777ffd7f6-htx6t               1/1     Running            0               3d2h
155
156
157$ kubectl get -o yaml -n openfaas-fn deploy/hello-openfaas2
158apiVersion: apps/v1
159kind: Deployment
160metadata:
161  annotations:
162    deployment.kubernetes.io/revision: "6"
163    prometheus.io.scrape: "false"
164  creationTimestamp: "2022-03-17T12:47:35Z"
165  generation: 6
166  labels:
167    faas_function: hello-openfaas2
168  name: hello-openfaas2
169  namespace: openfaas-fn
170  resourceVersion: "400833"
171  uid: 9c4e9d26-23af-4f93-8538-4e2d96f0d7e0
172spec:
173  progressDeadlineSeconds: 600
174  replicas: 1
175  revisionHistoryLimit: 10
176  selector:
177    matchLabels:
178      faas_function: hello-openfaas2
179  strategy:
180    rollingUpdate:
181      maxSurge: 1
182      maxUnavailable: 0
183    type: RollingUpdate
184  template:
185    metadata:
186      annotations:
187        prometheus.io.scrape: "false"
188      creationTimestamp: null
189      labels:
190        faas_function: hello-openfaas2
191        uid: "969512830"
192      name: hello-openfaas2
193    spec:
194      containers:
195      - env:
196        - name: fprocess
197          value: python3 index.py
198        image: wm/hello-openfaas2:0.1
199        imagePullPolicy: Always
200        livenessProbe:
201          failureThreshold: 3
202          httpGet:
203            path: /_/health
204            port: 8080
205            scheme: HTTP
206          initialDelaySeconds: 2
207          periodSeconds: 2
208          successThreshold: 1
209          timeoutSeconds: 1
210        name: hello-openfaas2
211        ports:
212        - containerPort: 8080
213          name: http
214          protocol: TCP
215        readinessProbe:
216          failureThreshold: 3
217          httpGet:
218            path: /_/health
219            port: 8080
220            scheme: HTTP
221          initialDelaySeconds: 2
222          periodSeconds: 2
223          successThreshold: 1
224          timeoutSeconds: 1
225        resources: {}
226        securityContext:
227          allowPrivilegeEscalation: false
228          readOnlyRootFilesystem: false
229        terminationMessagePath: /dev/termination-log
230        terminationMessagePolicy: File
231      dnsPolicy: ClusterFirst
232      enableServiceLinks: false
233      restartPolicy: Always
234      schedulerName: default-scheduler
235      securityContext: {}
236      terminationGracePeriodSeconds: 30
237status:
238  conditions:
239  - lastTransitionTime: "2022-03-17T12:47:35Z"
240    lastUpdateTime: "2022-03-17T12:47:35Z"
241    message: Deployment does not have minimum availability.
242    reason: MinimumReplicasUnavailable
243    status: "False"
244    type: Available
245  - lastTransitionTime: "2022-03-20T12:16:56Z"
246    lastUpdateTime: "2022-03-20T12:16:56Z"
247    message: ReplicaSet "hello-openfaas2-5d6c7c7fb4" has timed out progressing.
248    reason: ProgressDeadlineExceeded
249    status: "False"
250    type: Progressing
251  observedGeneration: 6
252  replicas: 2
253  unavailableReplicas: 2
254  updatedReplicas: 1
255docker@minikube:~$ docker run  --name wm -ti wm/hello-openfaas2:0.1
2562022/03/20 13:04:52 Version: 0.2.0  SHA: 56bf6aac54deb3863a690f5fc03a2a38e7d9e6ef
2572022/03/20 13:04:52 Timeouts: read: 5s write: 5s hard: 0s health: 5s.
2582022/03/20 13:04:52 Listening on port: 8080
259...
260
261docker@minikube:~$ docker ps | grep wm
262d7796286641c   wm/hello-openfaas2:0.1             "fwatchdog"              3 minutes ago       Up 3 minutes (healthy)   8080/tcp   wm
263

ANSWER

Answered 2022-Mar-16 at 08:10

If your image has a latest tag, the Pod's ImagePullPolicy will be automatically set to Always. Each time the pod is created, Kubernetes tries to pull the newest image.

Try not tagging the image as latest or manually setting the Pod's ImagePullPolicy to Never. If you're using static manifest to create a Pod, the setting will be like the following:

1$ docker images | grep hello-openfaas
2wm/hello-openfaas                                     latest                          bd08d01ce09b   34 minutes ago      65.2MB
3$ faas-cli deploy -f ./hello-openfaas.yml 
4Deploying: hello-openfaas.
5WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
6
7Deployed. 202 Accepted.
8URL: http://IP:8099/function/hello-openfaas
9see the helm chart for how to set the ImagePullPolicy
10$ kubectl logs -n openfaas-fn deploy/hello-openfaas
11Error from server (BadRequest): container "hello-openfaas" in pod "hello-openfaas-558f99477f-wd697" is waiting to start: trying and failing to pull image
12
13$ kubectl describe -n openfaas-fn deploy/hello-openfaas
14Name:                   hello-openfaas
15Namespace:              openfaas-fn
16CreationTimestamp:      Wed, 16 Mar 2022 14:59:49 +0800
17Labels:                 faas_function=hello-openfaas
18Annotations:            deployment.kubernetes.io/revision: 1
19                        prometheus.io.scrape: false
20Selector:               faas_function=hello-openfaas
21Replicas:               1 desired | 1 updated | 1 total | 0 available | 1 unavailable
22StrategyType:           RollingUpdate
23MinReadySeconds:        0
24RollingUpdateStrategy:  0 max unavailable, 1 max surge
25Pod Template:
26  Labels:       faas_function=hello-openfaas
27  Annotations:  prometheus.io.scrape: false
28  Containers:
29   hello-openfaas:
30    Image:      wm/hello-openfaas:latest
31    Port:       8080/TCP
32    Host Port:  0/TCP
33    Liveness:   http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
34    Readiness:  http-get http://:8080/_/health delay=2s timeout=1s period=2s #success=1 #failure=3
35    Environment:
36      fprocess:  python3 index.py
37    Mounts:      <none>
38  Volumes:       <none>
39Conditions:
40  Type           Status  Reason
41  ----           ------  ------
42  Available      False   MinimumReplicasUnavailable
43  Progressing    False   ProgressDeadlineExceeded
44OldReplicaSets:  <none>
45NewReplicaSet:   hello-openfaas-558f99477f (1/1 replicas created)
46Events:
47  Type    Reason             Age   From                   Message
48  ----    ------             ----  ----                   -------
49  Normal  ScalingReplicaSet  29m   deployment-controller  Scaled up replica set hello-openfaas-558f99477f to 1
50version: 1.0
51provider:
52  name: openfaas
53  gateway: http://IP:8099
54functions:
55  hello-openfaas:
56    lang: python3
57    handler: ./hello-openfaas
58    image: wm/hello-openfaas:latest
59    imagePullPolicy: Never
60$ faas-cli new --lang python3 hello-openfaas2 --prefix="wm"
61Folder: hello-openfaas2 created.
62# I add `imagePullPolicy: Never` to `hello-openfaas2.yml`
63$ faas-cli build -f ./hello-openfaas2.yml 
64$ faas-cli deploy -f ./hello-openfaas2.yml 
65Deploying: hello-openfaas2.
66WARNING! You are not using an encrypted connection to the gateway, consider using HTTPS.
67
68Deployed. 202 Accepted.
69URL: http://192.168.1.3:8099/function/hello-openfaas2
70
71
72$ kubectl logs -n openfaas-fn deploy/hello-openfaas2
73Error from server (BadRequest): container "hello-openfaas2" in pod "hello-openfaas2-7c67488865-7d7vm" is waiting to start: image can't be pulled
74
75$ kubectl get pods --all-namespaces
76NAMESPACE              NAME                                        READY   STATUS             RESTARTS         AGE
77kube-system            coredns-64897985d-kp7vf                     1/1     Running            0                47h
78...
79openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0                4h28m
80openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0                18h
81openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0                127m
82openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0                165m
83openfaas-fn            hello-openfaas2-7c67488865-qmrkl            0/1     ImagePullBackOff   0                13m
84openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0                97m
85openfaas-fn            hello-python-554b464498-zxcdv               0/1     ErrImagePull       0                3h23m
86openfaas-fn            hello-python-8698bc68bd-62gh9               0/1     ImagePullBackOff   0                3h25m
87$ docker images
88REPOSITORY                                TAG        IMAGE ID       CREATED             SIZE
89wm/hello-openfaas2                        0.1        03c21bd96d5e   About an hour ago   65.2MB
90python                                    3-alpine   69fba17b9bae   12 days ago         48.6MB
91ghcr.io/openfaas/figlet                   latest     ca5eef0de441   2 weeks ago         14.8MB
92ghcr.io/openfaas/alpine                   latest     35f3d4be6bb8   2 weeks ago         14.2MB
93ghcr.io/openfaas/faas-netes               0.14.2     524b510505ec   3 weeks ago         77.3MB
94k8s.gcr.io/kube-apiserver                 v1.23.3    f40be0088a83   7 weeks ago         135MB
95k8s.gcr.io/kube-controller-manager        v1.23.3    b07520cd7ab7   7 weeks ago         125MB
96k8s.gcr.io/kube-scheduler                 v1.23.3    99a3486be4f2   7 weeks ago         53.5MB
97k8s.gcr.io/kube-proxy                     v1.23.3    9b7cc9982109   7 weeks ago         112MB
98ghcr.io/openfaas/gateway                  0.21.3     ab4851262cd1   7 weeks ago         30.6MB
99ghcr.io/openfaas/basic-auth               0.21.3     16e7168a17a3   7 weeks ago         14.3MB
100k8s.gcr.io/etcd                           3.5.1-0    25f8c7f3da61   4 months ago        293MB
101ghcr.io/openfaas/classic-watchdog         0.2.0      6f97aa96da81   4 months ago        8.18MB
102k8s.gcr.io/coredns/coredns                v1.8.6     a4ca41631cc7   5 months ago        46.8MB
103k8s.gcr.io/pause                          3.6        6270bb605e12   6 months ago        683kB
104ghcr.io/openfaas/queue-worker             0.12.2     56e7216201bc   7 months ago        7.97MB
105kubernetesui/dashboard                    v2.3.1     e1482a24335a   9 months ago        220MB
106kubernetesui/metrics-scraper              v1.0.7     7801cfc6d5c0   9 months ago        34.4MB
107nats-streaming                            0.22.0     12f2d32e0c9a   9 months ago        19.8MB
108gcr.io/k8s-minikube/storage-provisioner   v5         6e38f40d628d   11 months ago       31.5MB
109functions/markdown-render                 latest     93b5da182216   2 years ago         24.6MB
110functions/hubstats                        latest     01affa91e9e4   2 years ago         29.3MB
111functions/nodeinfo                        latest     2fe8a87bf79c   2 years ago         71.4MB
112functions/alpine                          latest     46c6f6d74471   2 years ago         21.5MB
113prom/prometheus                           v2.11.0    b97ed892eb23   2 years ago         126MB
114prom/alertmanager                         v0.18.0    ce3c87f17369   2 years ago         51.9MB
115alexellis2/openfaas-colorization          0.4.1      d36b67b1b5c1   2 years ago         1.84GB
116rorpage/text-to-speech                    latest     5dc20810eb54   2 years ago         86.9MB
117stefanprodan/faas-grafana                 4.6.3      2a4bd9caea50   4 years ago         284MB
118
119$ kubectl get pods --all-namespaces
120NAMESPACE              NAME                                        READY   STATUS             RESTARTS        AGE
121kube-system            coredns-64897985d-kp7vf                     1/1     Running            0               6d
122kube-system            etcd-minikube                               1/1     Running            0               6d
123kube-system            kube-apiserver-minikube                     1/1     Running            0               6d
124kube-system            kube-controller-manager-minikube            1/1     Running            0               6d
125kube-system            kube-proxy-5m8lr                            1/1     Running            0               6d
126kube-system            kube-scheduler-minikube                     1/1     Running            0               6d
127kube-system            storage-provisioner                         1/1     Running            1 (6d ago)      6d
128kubernetes-dashboard   dashboard-metrics-scraper-58549894f-97tsv   1/1     Running            0               5d7h
129kubernetes-dashboard   kubernetes-dashboard-ccd587f44-lkwcx        1/1     Running            0               5d7h
130openfaas-fn            base64-6bdbcdb64c-djz8f                     1/1     Running            0               5d1h
131openfaas-fn            colorise-85c74c686b-2fz66                   1/1     Running            0               4d5h
132openfaas-fn            echoit-5d7df6684c-k6ljn                     1/1     Running            0               5d1h
133openfaas-fn            env-6c79f7b946-bzbtm                        1/1     Running            0               4d5h
134openfaas-fn            figlet-54db496f88-957xl                     1/1     Running            0               4d19h
135openfaas-fn            hello-openfaas-547857b9d6-z277c             0/1     ImagePullBackOff   0               4d3h
136openfaas-fn            hello-openfaas-7b6946b4f9-hcvq4             0/1     ImagePullBackOff   0               4d3h
137openfaas-fn            hello-openfaas2-5c6f6cb5d9-24hkz            0/1     ImagePullBackOff   0               9m22s
138openfaas-fn            hello-openfaas2-8957bb47b-7cgjg             0/1     ImagePullBackOff   0               2d22h
139openfaas-fn            hello-openfaas3-65847b8b67-b94kd            0/1     ImagePullBackOff   0               4d2h
140openfaas-fn            hello-python-6d6976845f-cwsln               0/1     ImagePullBackOff   0               3d19h
141openfaas-fn            hello-python-b577cb8dc-64wf5                0/1     ImagePullBackOff   0               3d9h
142openfaas-fn            hubstats-b6cd4dccc-z8tvl                    1/1     Running            0               5d1h
143openfaas-fn            markdown-68f69f47c8-w5m47                   1/1     Running            0               5d1h
144openfaas-fn            nodeinfo-d48cbbfcc-hfj79                    1/1     Running            0               5d1h
145openfaas-fn            openfaas2-fun                               1/1     Running            0               15s
146openfaas-fn            text-to-speech-74ffcdfd7-997t4              0/1     CrashLoopBackOff   2235 (3s ago)   4d5h
147openfaas-fn            wordcount-6489865566-cvfzr                  1/1     Running            0               5d1h
148openfaas               alertmanager-88449c789-fq2rg                1/1     Running            0               3d1h
149openfaas               basic-auth-plugin-75fd7d69c5-zw4jh          1/1     Running            0               3d2h
150openfaas               gateway-5c4bb7c5d7-n8h27                    2/2     Running            0               3d2h
151openfaas               grafana                                     1/1     Running            0               4d8h
152openfaas               nats-647b476664-hkr7p                       1/1     Running            0               3d2h
153openfaas               prometheus-687648749f-tl8jp                 1/1     Running            0               3d1h
154openfaas               queue-worker-7777ffd7f6-htx6t               1/1     Running            0               3d2h
155
156
157$ kubectl get -o yaml -n openfaas-fn deploy/hello-openfaas2
158apiVersion: apps/v1
159kind: Deployment
160metadata:
161  annotations:
162    deployment.kubernetes.io/revision: "6"
163    prometheus.io.scrape: "false"
164  creationTimestamp: "2022-03-17T12:47:35Z"
165  generation: 6
166  labels:
167    faas_function: hello-openfaas2
168  name: hello-openfaas2
169  namespace: openfaas-fn
170  resourceVersion: "400833"
171  uid: 9c4e9d26-23af-4f93-8538-4e2d96f0d7e0
172spec:
173  progressDeadlineSeconds: 600
174  replicas: 1
175  revisionHistoryLimit: 10
176  selector:
177    matchLabels:
178      faas_function: hello-openfaas2
179  strategy:
180    rollingUpdate:
181      maxSurge: 1
182      maxUnavailable: 0
183    type: RollingUpdate
184  template:
185    metadata:
186      annotations:
187        prometheus.io.scrape: "false"
188      creationTimestamp: null
189      labels:
190        faas_function: hello-openfaas2
191        uid: "969512830"
192      name: hello-openfaas2
193    spec:
194      containers:
195      - env:
196        - name: fprocess
197          value: python3 index.py
198        image: wm/hello-openfaas2:0.1
199        imagePullPolicy: Always
200        livenessProbe:
201          failureThreshold: 3
202          httpGet:
203            path: /_/health
204            port: 8080
205            scheme: HTTP
206          initialDelaySeconds: 2
207          periodSeconds: 2
208          successThreshold: 1
209          timeoutSeconds: 1
210        name: hello-openfaas2
211        ports:
212        - containerPort: 8080
213          name: http
214          protocol: TCP
215        readinessProbe:
216          failureThreshold: 3
217          httpGet:
218            path: /_/health
219            port: 8080
220            scheme: HTTP
221          initialDelaySeconds: 2
222          periodSeconds: 2
223          successThreshold: 1
224          timeoutSeconds: 1
225        resources: {}
226        securityContext:
227          allowPrivilegeEscalation: false
228          readOnlyRootFilesystem: false
229        terminationMessagePath: /dev/termination-log
230        terminationMessagePolicy: File
231      dnsPolicy: ClusterFirst
232      enableServiceLinks: false
233      restartPolicy: Always
234      schedulerName: default-scheduler
235      securityContext: {}
236      terminationGracePeriodSeconds: 30
237status:
238  conditions:
239  - lastTransitionTime: "2022-03-17T12:47:35Z"
240    lastUpdateTime: "2022-03-17T12:47:35Z"
241    message: Deployment does not have minimum availability.
242    reason: MinimumReplicasUnavailable
243    status: "False"
244    type: Available
245  - lastTransitionTime: "2022-03-20T12:16:56Z"
246    lastUpdateTime: "2022-03-20T12:16:56Z"
247    message: ReplicaSet "hello-openfaas2-5d6c7c7fb4" has timed out progressing.
248    reason: ProgressDeadlineExceeded
249    status: "False"
250    type: Progressing
251  observedGeneration: 6
252  replicas: 2
253  unavailableReplicas: 2
254  updatedReplicas: 1
255docker@minikube:~$ docker run  --name wm -ti wm/hello-openfaas2:0.1
2562022/03/20 13:04:52 Version: 0.2.0  SHA: 56bf6aac54deb3863a690f5fc03a2a38e7d9e6ef
2572022/03/20 13:04:52 Timeouts: read: 5s write: 5s hard: 0s health: 5s.
2582022/03/20 13:04:52 Listening on port: 8080
259...
260
261docker@minikube:~$ docker ps | grep wm
262d7796286641c   wm/hello-openfaas2:0.1             "fwatchdog"              3 minutes ago       Up 3 minutes (healthy)   8080/tcp   wm
263containers:
264  - name: test-container
265    image: testImage:latest
266    imagePullPolicy: Never
267

Source https://stackoverflow.com/questions/71493306

QUESTION

Add Kubernetes scrape target to Prometheus instance that is NOT in Kubernetes

Asked 2022-Feb-13 at 20:24

I run prometheus locally as http://localhost:9090/targets with

1docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus
2

and want to connect it to several Kubernetes (cluster) instances we have. See that scraping works, try Grafana dashboards etc.

And then I'll do the same on dedicated server that will be specially for monitoring. However all googling gives me all different ways to configure prometheus that is already within one Kubernetes instance, and no way to read metrics from external Kubernetes.

How to add Kubernetes scrape target to Prometheus instance that is NOT in Kubernetes?


I have read Where Kubernetes metrics come from and checked that my (first) Kubernetes cluster has the Metrics Server.

1docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus
2kubectl get pods --all-namespaces | grep metrics-server 
3

There is definitely no sense to add Prometheus instance into every Kubernetes (cluster) instance. One Prometheus must be able to read metrics from many Kubernetes clusters and every node within them.

P.S. Some old question has answer to install Prometheus in every Kubernetes and then use federation, that is just opposite from what I am looking for.

P.P.S. It is also strange for me, why Kubernetes and Prometheus that are #1 and #2 projects from Cloud Native Foundation don't have simple "add Kubernetes target in Prometheus" button or simple step.

ANSWER

Answered 2021-Dec-28 at 08:33

There are many agents capable of saving metrics collected in k8s to remote Prometheus server outside the cluster, example Prometheus itself now support agent mode, exporter from Opentelemetry, or using managed Prometheus etc.

Source https://stackoverflow.com/questions/70457308

QUESTION

Prometheus cannot scrape from spring-boot application over HTTPS

Asked 2022-Feb-11 at 19:34

I'm deploying a spring-boot application and prometheus container through docker, and have exposed the spring-boot /actuator/prometheus endpoint successfully. However, when I enable prometheus debug logs, I can see it fails to scrape the metrics:

1ts=2022-02-02T03:54:46.210Z
2caller=scrape.go:1292
3level=debug
4component="scrape manager"
5scrape_pool=spring-actuator
6target=https://127.0.0.1:8443/actuator/prometheus/
7msg="Scrape failed"
8err="Get \"https://127.0.0.1:8443/actuator/prometheus/\": dial tcp 127.0.0.1:8443: connect: connection refused"
9

I'm thinking it's something to do with how I've set up my spring-boot HTTPS. I am generating a self-signed certificate during the building of my spring-boot application, using the command:

1ts=2022-02-02T03:54:46.210Z
2caller=scrape.go:1292
3level=debug
4component="scrape manager"
5scrape_pool=spring-actuator
6target=https://127.0.0.1:8443/actuator/prometheus/
7msg="Scrape failed"
8err="Get \"https://127.0.0.1:8443/actuator/prometheus/\": dial tcp 127.0.0.1:8443: connect: connection refused"
9keytool
10  -genkey
11  -alias <alias>
12  -dname <dname>
13  -keyalg RSA
14  -keysize 4096
15  -storetype PKCS12
16  -keystore <path_to_keystore>
17  -validity 3650
18  -storepass <keystore_pass>
19

I then export the cert to a .pem file, and extract the .crt and .key:

1ts=2022-02-02T03:54:46.210Z
2caller=scrape.go:1292
3level=debug
4component="scrape manager"
5scrape_pool=spring-actuator
6target=https://127.0.0.1:8443/actuator/prometheus/
7msg="Scrape failed"
8err="Get \"https://127.0.0.1:8443/actuator/prometheus/\": dial tcp 127.0.0.1:8443: connect: connection refused"
9keytool
10  -genkey
11  -alias <alias>
12  -dname <dname>
13  -keyalg RSA
14  -keysize 4096
15  -storetype PKCS12
16  -keystore <path_to_keystore>
17  -validity 3650
18  -storepass <keystore_pass>
19openssl pkcs12 -in cert.p12 -out cert.pem -nodes -passin pass:<pass>
20

This is mounted through a shared volume to my prometheus container, which has a --web.config.file containing:

1ts=2022-02-02T03:54:46.210Z
2caller=scrape.go:1292
3level=debug
4component="scrape manager"
5scrape_pool=spring-actuator
6target=https://127.0.0.1:8443/actuator/prometheus/
7msg="Scrape failed"
8err="Get \"https://127.0.0.1:8443/actuator/prometheus/\": dial tcp 127.0.0.1:8443: connect: connection refused"
9keytool
10  -genkey
11  -alias <alias>
12  -dname <dname>
13  -keyalg RSA
14  -keysize 4096
15  -storetype PKCS12
16  -keystore <path_to_keystore>
17  -validity 3650
18  -storepass <keystore_pass>
19openssl pkcs12 -in cert.p12 -out cert.pem -nodes -passin pass:<pass>
20tls_server_config:
21  cert_file: /path/to/cert.crt
22  key_file: /path/to/cert.key
23

And for good measure I added insecure_skip_verify: true to the prometheus.yml config:

1ts=2022-02-02T03:54:46.210Z
2caller=scrape.go:1292
3level=debug
4component="scrape manager"
5scrape_pool=spring-actuator
6target=https://127.0.0.1:8443/actuator/prometheus/
7msg="Scrape failed"
8err="Get \"https://127.0.0.1:8443/actuator/prometheus/\": dial tcp 127.0.0.1:8443: connect: connection refused"
9keytool
10  -genkey
11  -alias <alias>
12  -dname <dname>
13  -keyalg RSA
14  -keysize 4096
15  -storetype PKCS12
16  -keystore <path_to_keystore>
17  -validity 3650
18  -storepass <keystore_pass>
19openssl pkcs12 -in cert.p12 -out cert.pem -nodes -passin pass:<pass>
20tls_server_config:
21  cert_file: /path/to/cert.crt
22  key_file: /path/to/cert.key
23- job_name: 'spring-actuator'
24metrics_path: '/actuator/prometheus/'
25scrape_interval: 60s
26scheme: https
27static_configs:
28  - targets: [ '127.0.0.1:8443' ]
29tls_config:
30  insecure_skip_verify: true
31

ANSWER

Answered 2022-Feb-07 at 22:37

Ok, I think I found my problem. I made two changes:

First, I moved the contents of the web.config.file into the prometheus.yml file under the 'spring-actuator'. Then I changed the target to use the hostname for my backend container, rather than 127.0.0.1.

The end result was a single prometheus.yml file:

1ts=2022-02-02T03:54:46.210Z
2caller=scrape.go:1292
3level=debug
4component="scrape manager"
5scrape_pool=spring-actuator
6target=https://127.0.0.1:8443/actuator/prometheus/
7msg="Scrape failed"
8err="Get \"https://127.0.0.1:8443/actuator/prometheus/\": dial tcp 127.0.0.1:8443: connect: connection refused"
9keytool
10  -genkey
11  -alias <alias>
12  -dname <dname>
13  -keyalg RSA
14  -keysize 4096
15  -storetype PKCS12
16  -keystore <path_to_keystore>
17  -validity 3650
18  -storepass <keystore_pass>
19openssl pkcs12 -in cert.p12 -out cert.pem -nodes -passin pass:<pass>
20tls_server_config:
21  cert_file: /path/to/cert.crt
22  key_file: /path/to/cert.key
23- job_name: 'spring-actuator'
24metrics_path: '/actuator/prometheus/'
25scrape_interval: 60s
26scheme: https
27static_configs:
28  - targets: [ '127.0.0.1:8443' ]
29tls_config:
30  insecure_skip_verify: true
31- job_name: 'spring-actuator'
32metrics_path: '/actuator/prometheus/'
33scrape_interval: 60s
34scheme: https
35static_configs:
36  - targets: [ 'backend:8443' ]
37tls_config:
38  cert_file: /path/to/cert.crt
39  key_file: /path/to/cert.key
40  insecure_skip_verify: true
41

So just some silly mistakes, not caused by the certs from what I can see. :)

Source https://stackoverflow.com/questions/70950420

QUESTION

Apply yaml file using k8s SDK

Asked 2022-Jan-17 at 16:00

I’ve the following yaml which I need to apply using the K8S go sdk (and not k8s cli) I didn’t find a way with the go sdk as it is custom resource, any idea how I can apply it via code to k8s?

This is the file

Any example will be very helpful!

1apiVersion: aps.dp.com/v1alpha1
2kind: Edtack
3metadata:
4  name: ed01
5  namespace: ctr
6spec:
7  intRef:
8    name: evr
9  stack:
10  - name: vectnt
11    namespace: aps
12    path: https://packages.timber.io/helm/latest/vect-0.11.0.tgz
13    valuesRef:
14      name: vecvalues
15  - name: ek
16    namespace: lg
17    path: rescharts/bing
18  - name: apigw-gloo-ee
19    namespace: apw
20    path: https://common.cdn.repositories.cloud.sap/api-gateway/apigw-gloo-ee/apigw-gloo-ee-0.3.0.tgz
21    pullSecretRef:
22      name: svr-secret
23    valuesSecretRef:
24      name: apis
25  - name: kuback
26    namespace: kube-prom
27    path: https://github.com/prometheus-community/helm-charts/releases/download/kube-prometheus-stack-16.12.0/kube-prometheus-stack-16.12.0.tgz
28    valuesSecretRef:
29      name: kubes
30

 

ANSWER

Answered 2022-Jan-17 at 16:00

You can use the k8sutil repo, see the apply example:

1apiVersion: aps.dp.com/v1alpha1
2kind: Edtack
3metadata:
4  name: ed01
5  namespace: ctr
6spec:
7  intRef:
8    name: evr
9  stack:
10  - name: vectnt
11    namespace: aps
12    path: https://packages.timber.io/helm/latest/vect-0.11.0.tgz
13    valuesRef:
14      name: vecvalues
15  - name: ek
16    namespace: lg
17    path: rescharts/bing
18  - name: apigw-gloo-ee
19    namespace: apw
20    path: https://common.cdn.repositories.cloud.sap/api-gateway/apigw-gloo-ee/apigw-gloo-ee-0.3.0.tgz
21    pullSecretRef:
22      name: svr-secret
23    valuesSecretRef:
24      name: apis
25  - name: kuback
26    namespace: kube-prom
27    path: https://github.com/prometheus-community/helm-charts/releases/download/kube-prometheus-stack-16.12.0/kube-prometheus-stack-16.12.0.tgz
28    valuesSecretRef:
29      name: kubes
30package main
31
32import (
33    "context"
34    "flag"
35    "log"
36    "path/filepath"
37
38    "github.com/pytimer/k8sutil/apply"
39
40    "k8s.io/client-go/discovery"
41    "k8s.io/client-go/dynamic"
42    "k8s.io/client-go/tools/clientcmd"
43    "k8s.io/client-go/util/homedir"
44)
45
46const applyStr = `
47apiVersion: apps/v1
48kind: Deployment
49metadata:
50  name: nginx
51spec:
52  replicas: 1
53  selector:
54    matchLabels:
55      app: nginx
56  template:
57    metadata:
58      labels:
59        app: nginx
60    spec:
61      containers:
62      - name: nginx
63        image: nginx
64---
65apiVersion: v1
66kind: Service
67metadata:
68  name: nginx-svc
69spec:
70  ports:
71  - name: web
72    port: 80
73    protocol: TCP
74    targetPort: 80
75  selector:
76    app: nginx
77  type: ClusterIP
78`
79
80func main() {
81    var kubeconfig *string
82    if home := homedir.HomeDir(); home != "" {
83        kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
84    } else {
85        kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
86    }
87    flag.Parse()
88
89    // use the current context in kubeconfig
90    config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
91    if err != nil {
92        panic(err.Error())
93    }
94
95    dynamicClient, err := dynamic.NewForConfig(config)
96    if err != nil {
97        panic(err.Error())
98    }
99    discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
100    if err != nil {
101        panic(err.Error())
102    }
103
104    applyOptions := apply.NewApplyOptions(dynamicClient, discoveryClient)
105    if err := applyOptions.Apply(context.TODO(), []byte(applyStr)); err != nil {
106        log.Fatalf("apply error: %v", err)
107    }
108}
109

Source https://stackoverflow.com/questions/69093178

QUESTION

Content of go.sum and modules really used by a go application

Asked 2022-Jan-12 at 17:09

I'm trying to compare the behavior of go mod tidy (and the resulting content of go.sum) to the output of go list -m all. Reading the docs, I understand go.sum contains the whole list of dependent modules declared in go.mod and in dependencies' go.mod files, go list -m all shows the modules really loaded during the execution. As an example, an application including logrus and prometheus like this:

go.mod

1module mytest
2
3go 1.14
4
5require (
6        github.com/prometheus/common v0.4.0
7        github.com/sirupsen/logrus v1.8.1
8)
9

main.go

1module mytest
2
3go 1.14
4
5require (
6        github.com/prometheus/common v0.4.0
7        github.com/sirupsen/logrus v1.8.1
8)
9package main
10
11import "github.com/sirupsen/logrus"
12import "github.com/prometheus/common/version"
13
14func main() {
15  logrus.Info("Hello World")
16  logrus.Infof("Prometheus info: %v", version.Info())
17}
18

After go mod tidy, go.sum shows both logrus v1.8.1, requested by the go.mod, and 1.2.0, dependency of prometheus v0.4.0; go list -m all shows only v1.8.1.

go.sum

1module mytest
2
3go 1.14
4
5require (
6        github.com/prometheus/common v0.4.0
7        github.com/sirupsen/logrus v1.8.1
8)
9package main
10
11import "github.com/sirupsen/logrus"
12import "github.com/prometheus/common/version"
13
14func main() {
15  logrus.Info("Hello World")
16  logrus.Infof("Prometheus info: %v", version.Info())
17}
18[...]
19github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
20github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
21github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
22[...]
23

output of go list

1module mytest
2
3go 1.14
4
5require (
6        github.com/prometheus/common v0.4.0
7        github.com/sirupsen/logrus v1.8.1
8)
9package main
10
11import "github.com/sirupsen/logrus"
12import "github.com/prometheus/common/version"
13
14func main() {
15  logrus.Info("Hello World")
16  logrus.Infof("Prometheus info: %v", version.Info())
17}
18[...]
19github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
20github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
21github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
22[...]
23[...]
24github.com/sirupsen/logrus v1.8.1
25[...]
26

Is it correct to say the modules really used by the application are listed by go list -m all?

The underlying problem is that a static code analysis detects insecure module versions listed in go.sum, but actually these versions don't show up in go list -m all, hence they shouldn't be really used by the application, but only downloaded during build phase to select the proper minimal version.

Some reference:

https://go.dev/ref/mod#go-mod-tidy

go mod tidy acts as if all build tags are enabled, so it will consider platform-specific source files and files that require custom build tags, even if those source files wouldn’t normally be built.

https://go.dev/ref/mod#go-sum-files

The go.sum file may contain hashes for multiple versions of a module. The go command may need to load go.mod files from multiple versions of a dependency in order to perform minimal version selection. go.sum may also contain hashes for module versions that aren’t needed anymore (for example, after an upgrade).

https://github.com/golang/go/wiki/Modules#is-gosum-a-lock-file-why-does-gosum-include-information-for-module-versions-i-am-no-longer-using

[...]In addition, your module's go.sum records checksums for all direct and indirect dependencies used in a build (and hence your go.sum will frequently have more modules listed than your go.mod).

https://github.com/golang/go/wiki/Modules#version-selection

The minimal version selection algorithm is used to select the versions of all modules used in a build. For each module in a build, the version selected by minimal version selection is always the semantically highest of the versions explicitly listed by a require directive in the main module or one of its dependencies.

As an example, if your module depends on module A which has a require D v1.0.0, and your module also depends on module B which has a require D v1.1.1, then minimal version selection would choose v1.1.1 of D to include in the build (given it is the highest listed require version). [...] To see a list of the selected module versions (including indirect dependencies), use go list -m all.

ANSWER

Answered 2022-Jan-12 at 17:09

Yes, it correct to say the modules really "used" by the application are listed by go list -m all (as per documentation you provided the link of). By "used", it means the package selected at build time for the compilation of the go code of your application.

We had a similar issue with a static analysis tool and we had to change the configuration to use the output of go list -m all (dumped in a file) instead of go.sum.

Source https://stackoverflow.com/questions/70128040

QUESTION

Is Google Managed Prometheus billing per million or per billion?

Asked 2022-Jan-03 at 09:25

The Google Managed Prometheus says that they cost $0.2 per million samples. However, in pricing examples they say:

Scenario 1: You have 100 containers, each writing 1,000 scalar times series.

Variant A: If each time series is written every 15 seconds (1 sample/15s), then the number of samples written per month is 17,420,000,000 (175,200 samples/month * 1,000 time series * 100 containers), or 17.42 million.

But 17,420,000,000 is 17.42 billion. So in that example, the price should be $3600, not $3.60, which is a pretty big difference to a pocket.

ANSWER

Answered 2021-Dec-14 at 13:24

You are right, this particular scenario is incorrect.
However, values in the table are correct - 18 million metrics would cost approximately $3.60.
Errors in documentation can be reported using the Public Issue Tracker.
You can also use the Google Cloud Pricing Calculator to estimate cost of your metrics.

Source https://stackoverflow.com/questions/70344734

QUESTION

Filter the parts of a Request Path which match against a Static Segment in Servant

Asked 2022-Jan-02 at 18:53

Supposing I'm running a Servant webserver, with two endpoints, with a type looking like this:

1type BookAPI =
2  "books" :> Get '[JSON] (Map Text Text)
3    :<|> "book" :> Capture "Name" Text :> ReqBody '[JSON] (Text) :> Post '[JSON] (Text)
4
1type BookAPI =
2  "books" :> Get '[JSON] (Map Text Text)
3    :<|> "book" :> Capture "Name" Text :> ReqBody '[JSON] (Text) :> Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ <capture>/
8│     └─•
9└─ books/
10   └─•
11

I might want to use something like Network.Wai.Middleware.Prometheus's instrumentHandlerValue to generate a Prometheus metric that fire's every time this API is called, with a handler value set to the path of the request.

However, if I do something like the following:

1type BookAPI =
2  "books" :> Get '[JSON] (Map Text Text)
3    :<|> "book" :> Capture "Name" Text :> ReqBody '[JSON] (Text) :> Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ <capture>/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate "\\" . pathInfo)
12

This is bad, because different requests to the book/<Name> endpoint, such as book/great-expectations and book/vanity-fair result in different labels, this is fine if the number of books is small, but if it's very large then the amount of data used by these metrics is very big, and either my service falls over, or my monitoring bill becomes very large.

I'd quite like a function, that took a Servant API, and a Wai Request, and if it matched, returned a list of segments in a form that was the same for each endpoint.

That is requests to /books would return Just ["books"], requests to /book/little-dorrit would return Just ["book", "Name"], and requests to /films would return Nothing.

I can kind of see how you might go about writing this by pattern matching on Router' from Servant.Server.Internal.Router, but it's not clear to me that relying on an internal package in order to do this is a good idea.

Is there a better way?

ANSWER

Answered 2022-Jan-02 at 18:53

The pathInfo function returns all the path segments for a Request. Perhaps we could define a typeclass that, given a Servant API, produced a "parser" for the list of segments, whose result would be a formatted version of the list.

The parser type could be something like:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17

Where the first [Text] in the state are the path segments yet to be parsed, and the second are the formatted path segments we have accumulated so far.

This type has an Alternative instance where failure discards state (basically backtracking) and a MonadFail instance that returns mzero on pattern-match failure inside do-blocks.

The typeclass:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17{-# LANGUAGE KindSignatures #-}
18{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE DataKinds #-}
20{-# LANGUAGE FlexibleInstances #-}
21{-# LANGUAGE TypeApplications #-}
22{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TypeOperators #-}
24{-# LANGUAGE OverloadedStrings #-}
25import Data.Data ( Proxy )
26import GHC.TypeLits
27
28class HasPathParser (x :: k) where
29    pathParser :: Proxy x -&gt; PathParser
30

The instance for Symbol moves the path piece from the pending list to the processed list:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17{-# LANGUAGE KindSignatures #-}
18{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE DataKinds #-}
20{-# LANGUAGE FlexibleInstances #-}
21{-# LANGUAGE TypeApplications #-}
22{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TypeOperators #-}
24{-# LANGUAGE OverloadedStrings #-}
25import Data.Data ( Proxy )
26import GHC.TypeLits
27
28class HasPathParser (x :: k) where
29    pathParser :: Proxy x -&gt; PathParser
30instance KnownSymbol piece =&gt; HasPathParser (piece :: Symbol) where
31  pathParser _ = do
32      (piece : rest, found) &lt;- get -- we are using MonadFail here
33      guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34      put (rest, piece : found)
35

The instance for Capture puts the name of the path variable—not the value—on the processed list:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17{-# LANGUAGE KindSignatures #-}
18{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE DataKinds #-}
20{-# LANGUAGE FlexibleInstances #-}
21{-# LANGUAGE TypeApplications #-}
22{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TypeOperators #-}
24{-# LANGUAGE OverloadedStrings #-}
25import Data.Data ( Proxy )
26import GHC.TypeLits
27
28class HasPathParser (x :: k) where
29    pathParser :: Proxy x -&gt; PathParser
30instance KnownSymbol piece =&gt; HasPathParser (piece :: Symbol) where
31  pathParser _ = do
32      (piece : rest, found) &lt;- get -- we are using MonadFail here
33      guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34      put (rest, piece : found)
35instance KnownSymbol name =&gt; HasPathParser (Capture name x) where
36  pathParser _ = do
37      (_ : rest, found) &lt;- get  -- we are using MonadFail here
38      put (rest, Data.Text.pack (symbolVal (Proxy @name)) : found)
39

When we reach a Verb (GET, POST...) we require that no pending path pieces should remain:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17{-# LANGUAGE KindSignatures #-}
18{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE DataKinds #-}
20{-# LANGUAGE FlexibleInstances #-}
21{-# LANGUAGE TypeApplications #-}
22{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TypeOperators #-}
24{-# LANGUAGE OverloadedStrings #-}
25import Data.Data ( Proxy )
26import GHC.TypeLits
27
28class HasPathParser (x :: k) where
29    pathParser :: Proxy x -&gt; PathParser
30instance KnownSymbol piece =&gt; HasPathParser (piece :: Symbol) where
31  pathParser _ = do
32      (piece : rest, found) &lt;- get -- we are using MonadFail here
33      guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34      put (rest, piece : found)
35instance KnownSymbol name =&gt; HasPathParser (Capture name x) where
36  pathParser _ = do
37      (_ : rest, found) &lt;- get  -- we are using MonadFail here
38      put (rest, Data.Text.pack (symbolVal (Proxy @name)) : found)
39instance HasPathParser (Verb method statusCode contextTypes a) where
40  pathParser _ = do
41      ([], found) &lt;- get -- we are using MonadFail here
42      put ([], found)
43

Some other instances:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17{-# LANGUAGE KindSignatures #-}
18{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE DataKinds #-}
20{-# LANGUAGE FlexibleInstances #-}
21{-# LANGUAGE TypeApplications #-}
22{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TypeOperators #-}
24{-# LANGUAGE OverloadedStrings #-}
25import Data.Data ( Proxy )
26import GHC.TypeLits
27
28class HasPathParser (x :: k) where
29    pathParser :: Proxy x -&gt; PathParser
30instance KnownSymbol piece =&gt; HasPathParser (piece :: Symbol) where
31  pathParser _ = do
32      (piece : rest, found) &lt;- get -- we are using MonadFail here
33      guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34      put (rest, piece : found)
35instance KnownSymbol name =&gt; HasPathParser (Capture name x) where
36  pathParser _ = do
37      (_ : rest, found) &lt;- get  -- we are using MonadFail here
38      put (rest, Data.Text.pack (symbolVal (Proxy @name)) : found)
39instance HasPathParser (Verb method statusCode contextTypes a) where
40  pathParser _ = do
41      ([], found) &lt;- get -- we are using MonadFail here
42      put ([], found)
43instance HasPathParser (ReqBody x y) where
44  pathParser _ = pure ()
45
46instance (HasPathParser a, HasPathParser b) =&gt; HasPathParser (a :&gt; b) where
47  pathParser _ = pathParser (Proxy @a) *&gt; pathParser (Proxy @b)
48
49instance (HasPathParser a, HasPathParser b) =&gt; HasPathParser (a :&lt;|&gt; b) where
50  pathParser _ = pathParser (Proxy @a) &lt;|&gt; pathParser (Proxy @b)
51

Putting it to work:

1type BookAPI =
2  &quot;books&quot; :&gt; Get '[JSON] (Map Text Text)
3    :&lt;|&gt; &quot;book&quot; :&gt; Capture &quot;Name&quot; Text :&gt; ReqBody '[JSON] (Text) :&gt; Post '[JSON] (Text)
4λ:T.putStrLn $ layout (Proxy :: Proxy BookAPI)
5/
6├─ book/
7│  └─ &lt;capture&gt;/
8│     └─•
9└─ books/
10   └─•
11prometheusMiddlware = instrumentHandlerValue (T.intercalate &quot;\\&quot; . pathInfo)
12import Data.Text 
13import Control.Monad.State.Strict
14import Control.Applicative
15
16type PathParser = StateT ([Text],[Text]) Maybe ()
17{-# LANGUAGE KindSignatures #-}
18{-# LANGUAGE PolyKinds #-}
19{-# LANGUAGE DataKinds #-}
20{-# LANGUAGE FlexibleInstances #-}
21{-# LANGUAGE TypeApplications #-}
22{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TypeOperators #-}
24{-# LANGUAGE OverloadedStrings #-}
25import Data.Data ( Proxy )
26import GHC.TypeLits
27
28class HasPathParser (x :: k) where
29    pathParser :: Proxy x -&gt; PathParser
30instance KnownSymbol piece =&gt; HasPathParser (piece :: Symbol) where
31  pathParser _ = do
32      (piece : rest, found) &lt;- get -- we are using MonadFail here
33      guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34      put (rest, piece : found)
35instance KnownSymbol name =&gt; HasPathParser (Capture name x) where
36  pathParser _ = do
37      (_ : rest, found) &lt;- get  -- we are using MonadFail here
38      put (rest, Data.Text.pack (symbolVal (Proxy @name)) : found)
39instance HasPathParser (Verb method statusCode contextTypes a) where
40  pathParser _ = do
41      ([], found) &lt;- get -- we are using MonadFail here
42      put ([], found)
43instance HasPathParser (ReqBody x y) where
44  pathParser _ = pure ()
45
46instance (HasPathParser a, HasPathParser b) =&gt; HasPathParser (a :&gt; b) where
47  pathParser _ = pathParser (Proxy @a) *&gt; pathParser (Proxy @b)
48
49instance (HasPathParser a, HasPathParser b) =&gt; HasPathParser (a :&lt;|&gt; b) where
50  pathParser _ = pathParser (Proxy @a) &lt;|&gt; pathParser (Proxy @b)
51main :: IO ()
52main = do
53    do let Just ([], result) = execStateT (pathParser (Proxy @BookAPI)) ([&quot;books&quot;],[])
54       print result
55       -- [&quot;books&quot;]
56    do let Just ([], result) = execStateT (pathParser (Proxy @BookAPI)) ([&quot;book&quot;, &quot;somebookid&quot;],[])
57       print result
58       -- [&quot;Name&quot;,&quot;book&quot;]
59

Source https://stackoverflow.com/questions/70439647

QUESTION

Can't deploy streamlit app on share.streamlit.io

Asked 2021-Dec-25 at 14:42

I am working with a simple ML model with streamlit. It runs fine on my local machine inside conda environment, but it shows Error installing requirements when I try to deploy it on share.streamlit.io.
The error message is the following:

1ERROR: Could not find a version that satisfies the requirement pywin32==303 (from versions: none)
2
3ERROR: No matching distribution found for pywin32==303
4

This is the requirements.txt file for my model:

1ERROR: Could not find a version that satisfies the requirement pywin32==303 (from versions: none)
2
3ERROR: No matching distribution found for pywin32==303
4altair==4.1.0
5argon2-cffi==21.3.0
6argon2-cffi-bindings==21.2.0
7astor==0.8.1
8attrs==21.2.0
9backcall==0.2.0
10base58==2.1.1
11bleach==4.1.0
12blinker==1.4
13cachetools==5.0.0
14certifi==2021.10.8
15cffi==1.15.0
16charset-normalizer==2.0.9
17click==7.1.2
18colorama==0.4.4
19cycler==0.11.0
20debugpy==1.5.1
21decorator==5.1.0
22defusedxml==0.7.1
23entrypoints==0.3
24fonttools==4.28.5
25gitdb==4.0.9
26GitPython==3.1.24
27idna==3.3
28ipykernel==6.6.0
29ipython==7.30.1
30ipython-genutils==0.2.0
31ipywidgets==7.6.5
32jedi==0.18.1
33Jinja2==3.0.3
34joblib==1.1.0
35jsonschema==4.3.2
36jupyter-client==7.1.0
37jupyter-core==4.9.1
38jupyterlab-pygments==0.1.2
39jupyterlab-widgets==1.0.2
40kiwisolver==1.3.2
41MarkupSafe==2.0.1
42matplotlib==3.5.1
43matplotlib-inline==0.1.3
44mistune==0.8.4
45nbclient==0.5.9
46nbconvert==6.3.0
47nbformat==5.1.3
48nest-asyncio==1.5.4
49notebook==6.4.6
50numpy==1.21.5
51packaging==21.3
52pandas==1.3.5
53pandocfilters==1.5.0
54parso==0.8.3
55pickleshare==0.7.5
56Pillow==8.4.0
57prometheus-client==0.12.0
58prompt-toolkit==3.0.24
59protobuf==3.19.1
60pyarrow==6.0.1
61pycparser==2.21
62pydeck==0.7.1
63Pygments==2.10.0
64Pympler==1.0.1
65pyparsing==3.0.6
66pyrsistent==0.18.0
67python-dateutil==2.8.2
68pytz==2021.3
69pytz-deprecation-shim==0.1.0.post0
70pywin32==303
71pywinpty==1.1.6
72pyzmq==22.3.0
73requests==2.26.0
74scikit-learn==1.0.1
75scipy==1.7.3
76seaborn==0.11.2
77Send2Trash==1.8.0
78six==1.16.0
79smmap==5.0.0
80streamlit==1.3.0
81terminado==0.12.1
82testpath==0.5.0
83threadpoolctl==3.0.0
84toml==0.10.2
85toolz==0.11.2
86tornado==6.1
87traitlets==5.1.1
88typing_extensions==4.0.1
89tzdata==2021.5
90tzlocal==4.1
91urllib3==1.26.7
92validators==0.18.2
93watchdog==2.1.6
94wcwidth==0.2.5
95webencodings==0.5.1
96widgetsnbextension==3.5.2
97wincertstore==0.2
98

What should I do to resolve this error?

ANSWER

Answered 2021-Dec-25 at 14:42

Streamlit share runs the app in a linux environment meaning there is no pywin32 because this is for windows.

Delete the pywin32 from the requirements file and also the pywinpty==1.1.6 for the same reason.

After deleting these requirements re-deploy your app and it will work.

Source https://stackoverflow.com/questions/70480314

QUESTION

OAUTH2 user service with Custom Authentication Providers

Asked 2021-Dec-08 at 11:45

I am new to Spring Security and Oauth2. In my spring boot application, I have implemented authentication with Oauth2 with following set of changes:

Custom Ouath2 User service is as follows:

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15

Security Configuration is as follows:

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86

Content of application.properties is as follows:

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98

Now, with the existing authentication mechanism, I would like to add support for multiple authentication providers: LDAP, Form-Login, etc.

In this regard, I have gone through a few articles:

  1. https://www.baeldung.com/spring-security-multiple-auth-providers
  2. Custom Authentication provider with Spring Security and Java Config

But, I am not getting any concrete idea regarding what changes should I do in the existing code base in order to achieve this.

Could anyone please help here? Thanks.

ANSWER

Answered 2021-Dec-08 at 11:45

I've created a simplified setup starting from your code with support for both OAuth2 and Basic Auth.

/tenant2/** will start a basic authentication. /** (everything else) triggers an OAuth2 Authorization Code authentication.

The key to achieve this is to have one @Configuration class per authentication type.

Let's start with the controllers:

Tenant1HomeController

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107

Tenant2HomeController

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110    @GetMapping(&quot;/tenant2/home&quot;)
111    public String home() {
112        return &quot;tenant2Home&quot;;
113    }
114
115}
116

Now, the configuration classes:

Tenant1SecurityConfiguration

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110    @GetMapping(&quot;/tenant2/home&quot;)
111    public String home() {
112        return &quot;tenant2Home&quot;;
113    }
114
115}
116@Configuration
117public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
118
119    @Override
120    protected void configure(HttpSecurity http) throws Exception {
121        http
122                .csrf().disable()
123                .authorizeRequests()
124                .antMatchers(&quot;/login**&quot;).permitAll()
125                .antMatchers(&quot;/manage/**&quot;).permitAll()
126                .antMatchers(&quot;/api/auth-info&quot;).permitAll()
127                .antMatchers(&quot;/api/**&quot;).authenticated()
128                .antMatchers(&quot;/management/health&quot;).permitAll()
129                .antMatchers(&quot;/management/info&quot;).permitAll()
130                .antMatchers(&quot;/management/prometheus&quot;).permitAll()
131                .antMatchers(&quot;/management/**&quot;).hasAuthority(&quot;ADMIN&quot;)
132                .antMatchers(&quot;/tenant1/**&quot;).authenticated()
133                .and()
134                .oauth2Login()
135                .and()
136                .cors()
137                .disable();
138    }
139}
140

Tenant2SecurityConfiguration (Notice the @Order(90), that's important

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110    @GetMapping(&quot;/tenant2/home&quot;)
111    public String home() {
112        return &quot;tenant2Home&quot;;
113    }
114
115}
116@Configuration
117public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
118
119    @Override
120    protected void configure(HttpSecurity http) throws Exception {
121        http
122                .csrf().disable()
123                .authorizeRequests()
124                .antMatchers(&quot;/login**&quot;).permitAll()
125                .antMatchers(&quot;/manage/**&quot;).permitAll()
126                .antMatchers(&quot;/api/auth-info&quot;).permitAll()
127                .antMatchers(&quot;/api/**&quot;).authenticated()
128                .antMatchers(&quot;/management/health&quot;).permitAll()
129                .antMatchers(&quot;/management/info&quot;).permitAll()
130                .antMatchers(&quot;/management/prometheus&quot;).permitAll()
131                .antMatchers(&quot;/management/**&quot;).hasAuthority(&quot;ADMIN&quot;)
132                .antMatchers(&quot;/tenant1/**&quot;).authenticated()
133                .and()
134                .oauth2Login()
135                .and()
136                .cors()
137                .disable();
138    }
139}
140@Order(90)
141@Configuration
142public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {
143
144    @Override
145    protected void configure(HttpSecurity http) throws Exception {
146        http.requestMatcher(new AntPathRequestMatcher(&quot;/tenant2/**&quot;))
147                .csrf()
148                .disable()
149                .authorizeRequests()
150                .antMatchers(&quot;/tenant2/**&quot;).hasAuthority(&quot;BASIC_USER&quot;)
151                .and()
152                .httpBasic();
153        http.cors().disable();
154    }
155
156    @Override
157    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
158        auth.inMemoryAuthentication()
159                .withUser(&quot;user&quot;)
160                .password(&quot;{noop}password&quot;)
161                .roles(&quot;BASIC_USER&quot;);
162    }
163}
164

Finally the configuration:

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110    @GetMapping(&quot;/tenant2/home&quot;)
111    public String home() {
112        return &quot;tenant2Home&quot;;
113    }
114
115}
116@Configuration
117public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
118
119    @Override
120    protected void configure(HttpSecurity http) throws Exception {
121        http
122                .csrf().disable()
123                .authorizeRequests()
124                .antMatchers(&quot;/login**&quot;).permitAll()
125                .antMatchers(&quot;/manage/**&quot;).permitAll()
126                .antMatchers(&quot;/api/auth-info&quot;).permitAll()
127                .antMatchers(&quot;/api/**&quot;).authenticated()
128                .antMatchers(&quot;/management/health&quot;).permitAll()
129                .antMatchers(&quot;/management/info&quot;).permitAll()
130                .antMatchers(&quot;/management/prometheus&quot;).permitAll()
131                .antMatchers(&quot;/management/**&quot;).hasAuthority(&quot;ADMIN&quot;)
132                .antMatchers(&quot;/tenant1/**&quot;).authenticated()
133                .and()
134                .oauth2Login()
135                .and()
136                .cors()
137                .disable();
138    }
139}
140@Order(90)
141@Configuration
142public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {
143
144    @Override
145    protected void configure(HttpSecurity http) throws Exception {
146        http.requestMatcher(new AntPathRequestMatcher(&quot;/tenant2/**&quot;))
147                .csrf()
148                .disable()
149                .authorizeRequests()
150                .antMatchers(&quot;/tenant2/**&quot;).hasAuthority(&quot;BASIC_USER&quot;)
151                .and()
152                .httpBasic();
153        http.cors().disable();
154    }
155
156    @Override
157    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
158        auth.inMemoryAuthentication()
159                .withUser(&quot;user&quot;)
160                .password(&quot;{noop}password&quot;)
161                .roles(&quot;BASIC_USER&quot;);
162    }
163}
164spring:
165  security:
166    oauth2:
167      client:
168        registration:
169          keycloak:
170            client-id: myclient
171            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
172        provider:
173          keycloak:
174            issuer-uri: http://localhost:8180/auth/realms/myrealm
175

With this in place, if we hit http://localhost:8080/tenant2/home, will be prompted with the basic auth popup:

enter image description here

Trying with http://localhost:8080/tenant1/home sends you to Keycloak's login form:

enter image description here

UPDATE:

It's completely viable to configure a multitenant application with the configuration above.

The key would be that each authentication provider works with a different set of users (tenants), e.g.:

TENANT 1 (OAuth2 authentication):

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110    @GetMapping(&quot;/tenant2/home&quot;)
111    public String home() {
112        return &quot;tenant2Home&quot;;
113    }
114
115}
116@Configuration
117public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
118
119    @Override
120    protected void configure(HttpSecurity http) throws Exception {
121        http
122                .csrf().disable()
123                .authorizeRequests()
124                .antMatchers(&quot;/login**&quot;).permitAll()
125                .antMatchers(&quot;/manage/**&quot;).permitAll()
126                .antMatchers(&quot;/api/auth-info&quot;).permitAll()
127                .antMatchers(&quot;/api/**&quot;).authenticated()
128                .antMatchers(&quot;/management/health&quot;).permitAll()
129                .antMatchers(&quot;/management/info&quot;).permitAll()
130                .antMatchers(&quot;/management/prometheus&quot;).permitAll()
131                .antMatchers(&quot;/management/**&quot;).hasAuthority(&quot;ADMIN&quot;)
132                .antMatchers(&quot;/tenant1/**&quot;).authenticated()
133                .and()
134                .oauth2Login()
135                .and()
136                .cors()
137                .disable();
138    }
139}
140@Order(90)
141@Configuration
142public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {
143
144    @Override
145    protected void configure(HttpSecurity http) throws Exception {
146        http.requestMatcher(new AntPathRequestMatcher(&quot;/tenant2/**&quot;))
147                .csrf()
148                .disable()
149                .authorizeRequests()
150                .antMatchers(&quot;/tenant2/**&quot;).hasAuthority(&quot;BASIC_USER&quot;)
151                .and()
152                .httpBasic();
153        http.cors().disable();
154    }
155
156    @Override
157    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
158        auth.inMemoryAuthentication()
159                .withUser(&quot;user&quot;)
160                .password(&quot;{noop}password&quot;)
161                .roles(&quot;BASIC_USER&quot;);
162    }
163}
164spring:
165  security:
166    oauth2:
167      client:
168        registration:
169          keycloak:
170            client-id: myclient
171            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
172        provider:
173          keycloak:
174            issuer-uri: http://localhost:8180/auth/realms/myrealm
175@Configuration
176public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
177
178    @Override
179    protected void configure(HttpSecurity http) throws Exception {
180        http.
181            ...
182            .and()
183            .oauth2Login()
184            .and()
185            ...
186            
187

This first subset of users is federated by the OAuth2 provider, Keycloak in this case.

TENANT 2 (Basic / form /xxx authentication):

1  @Component
2  public class CustomOAuth2UserService extends DefaultOAuth2UserService {
3
4     private UserRepository userRepository;
5
6     @Autowired
7     public void setUserRepository(UserRepository userRepository) {
8        this.userRepository = userRepository;
9     }
10
11    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
12        ...
13    }
14 }
15@EnableWebSecurity
16@Import(SecurityProblemSupport.class)
17@ConditionalOnProperty(
18        value = &quot;myapp.authentication.type&quot;,
19        havingValue = &quot;oauth&quot;,
20        matchIfMissing = true
21)
22public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
23  private final CustomOAuth2UserService customOAuth2UserService;
24    
25  public SecurityConfiguration(CustomOAuth2UserService customOAuth2UserService) {
26    this.customOAuth2UserService = customOAuth2UserService;
27  }
28
29  @Override
30  public void configure(WebSecurity web) {
31    web.ignoring()
32        .antMatchers(HttpMethod.OPTIONS, &quot;/**&quot;)
33        .antMatchers(&quot;/app/**/*.{js,html}&quot;)
34        .antMatchers(&quot;/bundle.js&quot;)
35        .antMatchers(&quot;/slds-icons/**&quot;)
36        .antMatchers(&quot;/assets/**&quot;)
37        .antMatchers(&quot;/i18n/**&quot;)
38        .antMatchers(&quot;/content/**&quot;)
39        .antMatchers(&quot;/swagger-ui/**&quot;)
40        .antMatchers(&quot;/swagger-resources&quot;)
41        .antMatchers(&quot;/v2/api-docs&quot;)
42        .antMatchers(&quot;/api/redirectToHome&quot;)
43        .antMatchers(&quot;/test/**&quot;);
44  }
45
46  public void configure(HttpSecurity http) throws Exception {
47    RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48      private RegexRequestMatcher requestMatcher =
49          new RegexRequestMatcher(&quot;/api/&quot;, null);
50
51      @Override
52      public boolean matches(HttpServletRequest request) {
53        return requestMatcher.matches(request);
54      }
55    };
56
57    http.csrf()
58        .requireCsrfProtectionMatcher(csrfRequestMatcher)
59        .and()
60        .authorizeRequests()
61        .antMatchers(&quot;/login**&quot;).permitAll()
62        .antMatchers(&quot;/manage/**&quot;).permitAll()
63        .antMatchers(&quot;/api/auth-info&quot;).permitAll()
64        .antMatchers(&quot;/api/**&quot;).authenticated()
65        .antMatchers(&quot;/management/health&quot;).permitAll()
66        .antMatchers(&quot;/management/info&quot;).permitAll()
67        .antMatchers(&quot;/management/prometheus&quot;).permitAll()
68        .antMatchers(&quot;/management/**&quot;).hasAuthority(AuthoritiesConstants.ADMIN)
69        .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70        .and()
71        .oauth2Login()
72        .redirectionEndpoint()
73        .baseUri(&quot;/oauth2**&quot;)
74        .and()
75        .failureUrl(&quot;/api/redirectToHome&quot;)
76        .userInfoEndpoint().userService(oauth2UserService())
77    ;
78    http.cors().disable();
79  }
80
81
82  private OAuth2UserService&lt;OAuth2UserRequest, OAuth2User&gt; oauth2UserService() {
83    return customOAuth2UserService;
84  }
85}
86spring.security.oauth2.client.registration.keycloak.client-id=abcd
87spring.security.oauth2.client.registration.keycloak.client-name=Auth Server
88spring.security.oauth2.client.registration.keycloak.scope=api
89spring.security.oauth2.client.registration.keycloak.provider=keycloak
90spring.security.oauth2.client.registration.keycloak.client-authentication-method=basic
91spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
92myapp.oauth2.path=https://internal.authprovider.com/oauth2/
93spring.security.oauth2.client.provider.keycloak.token-uri=${myapp.oauth2.path}token
94spring.security.oauth2.client.provider.keycloak.authorization-uri=${myapp.oauth2.path}authorize
95spring.security.oauth2.client.provider.keycloak.user-info-uri=${myapp.oauth2.path}userinfo
96spring.security.oauth2.client.provider.keycloak.user-name-attribute=name
97myapp.authentication.type=oauth
98@Controller
99public class Tenant1HomeController {
100
101    @GetMapping(&quot;/tenant1/home&quot;)
102    public String home() {
103        return &quot;tenant1Home&quot;;
104    }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110    @GetMapping(&quot;/tenant2/home&quot;)
111    public String home() {
112        return &quot;tenant2Home&quot;;
113    }
114
115}
116@Configuration
117public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
118
119    @Override
120    protected void configure(HttpSecurity http) throws Exception {
121        http
122                .csrf().disable()
123                .authorizeRequests()
124                .antMatchers(&quot;/login**&quot;).permitAll()
125                .antMatchers(&quot;/manage/**&quot;).permitAll()
126                .antMatchers(&quot;/api/auth-info&quot;).permitAll()
127                .antMatchers(&quot;/api/**&quot;).authenticated()
128                .antMatchers(&quot;/management/health&quot;).permitAll()
129                .antMatchers(&quot;/management/info&quot;).permitAll()
130                .antMatchers(&quot;/management/prometheus&quot;).permitAll()
131                .antMatchers(&quot;/management/**&quot;).hasAuthority(&quot;ADMIN&quot;)
132                .antMatchers(&quot;/tenant1/**&quot;).authenticated()
133                .and()
134                .oauth2Login()
135                .and()
136                .cors()
137                .disable();
138    }
139}
140@Order(90)
141@Configuration
142public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {
143
144    @Override
145    protected void configure(HttpSecurity http) throws Exception {
146        http.requestMatcher(new AntPathRequestMatcher(&quot;/tenant2/**&quot;))
147                .csrf()
148                .disable()
149                .authorizeRequests()
150                .antMatchers(&quot;/tenant2/**&quot;).hasAuthority(&quot;BASIC_USER&quot;)
151                .and()
152                .httpBasic();
153        http.cors().disable();
154    }
155
156    @Override
157    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
158        auth.inMemoryAuthentication()
159                .withUser(&quot;user&quot;)
160                .password(&quot;{noop}password&quot;)
161                .roles(&quot;BASIC_USER&quot;);
162    }
163}
164spring:
165  security:
166    oauth2:
167      client:
168        registration:
169          keycloak:
170            client-id: myclient
171            client-secret: c6dce03e-ea13-4b76-8aab-c876f5c2c1d9
172        provider:
173          keycloak:
174            issuer-uri: http://localhost:8180/auth/realms/myrealm
175@Configuration
176public class Tenant1SecurityConfiguration extends WebSecurityConfigurerAdapter {
177
178    @Override
179    protected void configure(HttpSecurity http) throws Exception {
180        http.
181            ...
182            .and()
183            .oauth2Login()
184            .and()
185            ...
186            
187@Order(90)
188@Configuration
189public class Tenant2SecurityConfiguration extends WebSecurityConfigurerAdapter {
190
191    @Override
192    protected void configure(HttpSecurity http) throws Exception {
193        ...
194    }
195
196    @Override
197    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
198        auth.userDetailsService(XXX)
199

For the second tenant, you can use a userDetailsService that points to a different repository of users (LDAP, database...).

Source https://stackoverflow.com/questions/70194951

QUESTION

Prometheus kubelet metrics with pod labels

Asked 2021-Dec-03 at 10:41

I am trying to figure out how to get pod labels into the metric tags from kubelet metrics using prometheus-stack. In our environment, we need to hash pod names (due to length limitations) so our app name, env, and unit name are saved in pod labels.

We are using prometheus-stack (helm installation) to collect metrics from kubelet (/metrics, /metrics/cadvisor) and due to the lack of pod labels in metrics tags, it's difficult to know which metric belongs to which application.

Prometheus-stack is using sd_kubernetes_config with endpoint rule to collect kubelet metrics, where __meta tags for pod labels cannot be used. Is there another way how to get that labels in metric tags?

I also tried to collect pod_labels metric using kubeStateMetrics, where I can get metric that contains pod labels, but I cannot figure out how to display both metrics in a way that metric from cadvisor will show its value and metric from kubeStateMetrics will be used to display its labels (in Prometheus graph).

Thanks for any advice.

ANSWER

Answered 2021-Dec-02 at 08:39

As far as I know you can really use filtering metrics based on pod labels. Look at the original answer:

You can use + operator to join metrics. Here, group_left() will include the extra label: label_source from the right metric kube_pod_labels. The metric you're joining is forced to zero ( i.e. 0 * kube_pod_labels ) so that it doesn't affect the result of first metric.

1(
2kube_pod_info{namespace=&quot;test&quot;}
3)
4   + on(namespace) group_left(label_source)
5(
6   0 * kube_pod_labels
7)
8

In fact, metrics then can be long and nasty. However, it is an effective method in prometheus to create what you expect, which is kubelet metrics with pod labels.

Look also at this guide - it is described how to join Prometheus metrics by label with PromQL and this another guide - How to use PromQL joins for more effective queries of Prometheus metrics at scale.

Source https://stackoverflow.com/questions/70092161

Community Discussions contain sources that include Stack Exchange Network

Tutorials and Learning Resources in Prometheus

Tutorials and Learning Resources are not available at this moment for Prometheus

Share this Page

share link

Get latest updates on Prometheus