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
by netdata c
58912 GPL-3.0
Real-time performance monitoring, done right! https://www.netdata.cloud
by grafana typescript
48159 AGPL-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.
by prometheus go
42027 Apache-2.0
The Prometheus monitoring system and time series database.
by bregman-arie python
22045 NOASSERTION
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
by openfaas go
20981 MIT
OpenFaaS - Serverless Functions Made Simple
by apache java
19150 Apache-2.0
APM, Application Performance Monitoring System
by dianping java
16597 Apache-2.0
CAT 作为服务端项目基础组件,提供了 Java, C/C++, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等,消息队列,配置系统等)深度集成,为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。
by grafana go
15577 AGPL-3.0
Like Prometheus, but for logs.
by openzipkin java
15220 Apache-2.0
Zipkin is a distributed tracing system
Trending New libraries in Prometheus
by SigNoz typescript
6127 MIT
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
by didi go
4433 Apache-2.0
An enterprise-level cloud-native monitoring system, which can be used as drop-in replacement of Prometheus for alerting and management.
by douyu go
3691 Apache-2.0
Jupiter是斗鱼开源的面向服务治理的Golang微服务框架
by microsoft go
3213 MIT
Linux OS for Azure 1P services and edge appliances
by erda-project go
2294 Apache-2.0
An enterprise-grade Cloud-Native application platform for Kubernetes.
by grafana go
1958 AGPL-3.0
Grafana Tempo is a high volume, minimal dependency distributed tracing backend.
by yolossn go
1505 MIT
A beginner friendly introduction to prometheus 🔥
by slok go
1033 Apache-2.0
🦥 Easy and simple Prometheus SLO (service level objectives) generator
by opstrace typescript
1012 Apache-2.0
The Open Source Observability Distribution
Top Authors in Prometheus
1
42 Libraries
466
2
25 Libraries
71434
3
25 Libraries
67872
4
19 Libraries
3930
5
18 Libraries
5062
6
15 Libraries
356
7
15 Libraries
296
8
14 Libraries
180
9
13 Libraries
624
10
11 Libraries
5124
1
42 Libraries
466
2
25 Libraries
71434
3
25 Libraries
67872
4
19 Libraries
3930
5
18 Libraries
5062
6
15 Libraries
356
7
15 Libraries
296
8
14 Libraries
180
9
13 Libraries
624
10
11 Libraries
5124
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:23I'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:10If 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
QUESTION
Add Kubernetes scrape target to Prometheus instance that is NOT in Kubernetes
Asked 2022-Feb-13 at 20:24I 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:33There 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.
QUESTION
Prometheus cannot scrape from spring-boot application over HTTPS
Asked 2022-Feb-11 at 19:34I'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:37Ok, 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. :)
QUESTION
Apply yaml file using k8s SDK
Asked 2022-Jan-17 at 16:00I’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:001apiVersion: 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
QUESTION
Content of go.sum and modules really used by a go application
Asked 2022-Jan-12 at 17:09I'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).
[...]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 arequire D v1.0.0
, and your module also depends on moduleB
which has arequire 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), usego list -m all
.
ANSWER
Answered 2022-Jan-12 at 17:09Yes, 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
.
QUESTION
Is Google Managed Prometheus billing per million or per billion?
Asked 2022-Jan-03 at 09:25The 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:24You 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.
QUESTION
Filter the parts of a Request Path which match against a Static Segment in Servant
Asked 2022-Jan-02 at 18:53Supposing 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:53The 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 "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)
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 "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)
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 -> PathParser
30
The instance for Symbol
moves the path piece from the pending list to the processed list:
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)
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 -> PathParser
30instance KnownSymbol piece => HasPathParser (piece :: Symbol) where
31 pathParser _ = do
32 (piece : rest, found) <- 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 "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)
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 -> PathParser
30instance KnownSymbol piece => HasPathParser (piece :: Symbol) where
31 pathParser _ = do
32 (piece : rest, found) <- get -- we are using MonadFail here
33 guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34 put (rest, piece : found)
35instance KnownSymbol name => HasPathParser (Capture name x) where
36 pathParser _ = do
37 (_ : rest, found) <- get -- we are using MonadFail here
38 put (rest, Data.Text.pack (symbolVal (Proxy @name)) : found)
39
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)
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 -> PathParser
30instance KnownSymbol piece => HasPathParser (piece :: Symbol) where
31 pathParser _ = do
32 (piece : rest, found) <- get -- we are using MonadFail here
33 guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34 put (rest, piece : found)
35instance KnownSymbol name => HasPathParser (Capture name x) where
36 pathParser _ = do
37 (_ : rest, found) <- 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) <- get -- we are using MonadFail here
42 put ([], found)
43
Some other instances:
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)
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 -> PathParser
30instance KnownSymbol piece => HasPathParser (piece :: Symbol) where
31 pathParser _ = do
32 (piece : rest, found) <- get -- we are using MonadFail here
33 guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34 put (rest, piece : found)
35instance KnownSymbol name => HasPathParser (Capture name x) where
36 pathParser _ = do
37 (_ : rest, found) <- 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) <- get -- we are using MonadFail here
42 put ([], found)
43instance HasPathParser (ReqBody x y) where
44 pathParser _ = pure ()
45
46instance (HasPathParser a, HasPathParser b) => HasPathParser (a :> b) where
47 pathParser _ = pathParser (Proxy @a) *> pathParser (Proxy @b)
48
49instance (HasPathParser a, HasPathParser b) => HasPathParser (a :<|> b) where
50 pathParser _ = pathParser (Proxy @a) <|> pathParser (Proxy @b)
51
Putting it to work:
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)
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 -> PathParser
30instance KnownSymbol piece => HasPathParser (piece :: Symbol) where
31 pathParser _ = do
32 (piece : rest, found) <- get -- we are using MonadFail here
33 guard (piece == Data.Text.pack (symbolVal (Proxy @piece)))
34 put (rest, piece : found)
35instance KnownSymbol name => HasPathParser (Capture name x) where
36 pathParser _ = do
37 (_ : rest, found) <- 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) <- get -- we are using MonadFail here
42 put ([], found)
43instance HasPathParser (ReqBody x y) where
44 pathParser _ = pure ()
45
46instance (HasPathParser a, HasPathParser b) => HasPathParser (a :> b) where
47 pathParser _ = pathParser (Proxy @a) *> pathParser (Proxy @b)
48
49instance (HasPathParser a, HasPathParser b) => HasPathParser (a :<|> b) where
50 pathParser _ = pathParser (Proxy @a) <|> pathParser (Proxy @b)
51main :: IO ()
52main = do
53 do let Just ([], result) = execStateT (pathParser (Proxy @BookAPI)) (["books"],[])
54 print result
55 -- ["books"]
56 do let Just ([], result) = execStateT (pathParser (Proxy @BookAPI)) (["book", "somebookid"],[])
57 print result
58 -- ["Name","book"]
59
QUESTION
Can't deploy streamlit app on share.streamlit.io
Asked 2021-Dec-25 at 14:42I 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:42Streamlit 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.
QUESTION
OAUTH2 user service with Custom Authentication Providers
Asked 2021-Dec-08 at 11:45I 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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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:
- https://www.baeldung.com/spring-security-multiple-auth-providers
- 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:45I'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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
104 }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110 @GetMapping("/tenant2/home")
111 public String home() {
112 return "tenant2Home";
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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
104 }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110 @GetMapping("/tenant2/home")
111 public String home() {
112 return "tenant2Home";
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("/login**").permitAll()
125 .antMatchers("/manage/**").permitAll()
126 .antMatchers("/api/auth-info").permitAll()
127 .antMatchers("/api/**").authenticated()
128 .antMatchers("/management/health").permitAll()
129 .antMatchers("/management/info").permitAll()
130 .antMatchers("/management/prometheus").permitAll()
131 .antMatchers("/management/**").hasAuthority("ADMIN")
132 .antMatchers("/tenant1/**").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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
104 }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110 @GetMapping("/tenant2/home")
111 public String home() {
112 return "tenant2Home";
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("/login**").permitAll()
125 .antMatchers("/manage/**").permitAll()
126 .antMatchers("/api/auth-info").permitAll()
127 .antMatchers("/api/**").authenticated()
128 .antMatchers("/management/health").permitAll()
129 .antMatchers("/management/info").permitAll()
130 .antMatchers("/management/prometheus").permitAll()
131 .antMatchers("/management/**").hasAuthority("ADMIN")
132 .antMatchers("/tenant1/**").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("/tenant2/**"))
147 .csrf()
148 .disable()
149 .authorizeRequests()
150 .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
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("user")
160 .password("{noop}password")
161 .roles("BASIC_USER");
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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
104 }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110 @GetMapping("/tenant2/home")
111 public String home() {
112 return "tenant2Home";
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("/login**").permitAll()
125 .antMatchers("/manage/**").permitAll()
126 .antMatchers("/api/auth-info").permitAll()
127 .antMatchers("/api/**").authenticated()
128 .antMatchers("/management/health").permitAll()
129 .antMatchers("/management/info").permitAll()
130 .antMatchers("/management/prometheus").permitAll()
131 .antMatchers("/management/**").hasAuthority("ADMIN")
132 .antMatchers("/tenant1/**").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("/tenant2/**"))
147 .csrf()
148 .disable()
149 .authorizeRequests()
150 .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
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("user")
160 .password("{noop}password")
161 .roles("BASIC_USER");
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:
Trying with http://localhost:8080/tenant1/home
sends you to Keycloak's login form:
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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
104 }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110 @GetMapping("/tenant2/home")
111 public String home() {
112 return "tenant2Home";
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("/login**").permitAll()
125 .antMatchers("/manage/**").permitAll()
126 .antMatchers("/api/auth-info").permitAll()
127 .antMatchers("/api/**").authenticated()
128 .antMatchers("/management/health").permitAll()
129 .antMatchers("/management/info").permitAll()
130 .antMatchers("/management/prometheus").permitAll()
131 .antMatchers("/management/**").hasAuthority("ADMIN")
132 .antMatchers("/tenant1/**").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("/tenant2/**"))
147 .csrf()
148 .disable()
149 .authorizeRequests()
150 .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
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("user")
160 .password("{noop}password")
161 .roles("BASIC_USER");
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 = "myapp.authentication.type",
19 havingValue = "oauth",
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, "/**")
33 .antMatchers("/app/**/*.{js,html}")
34 .antMatchers("/bundle.js")
35 .antMatchers("/slds-icons/**")
36 .antMatchers("/assets/**")
37 .antMatchers("/i18n/**")
38 .antMatchers("/content/**")
39 .antMatchers("/swagger-ui/**")
40 .antMatchers("/swagger-resources")
41 .antMatchers("/v2/api-docs")
42 .antMatchers("/api/redirectToHome")
43 .antMatchers("/test/**");
44 }
45
46 public void configure(HttpSecurity http) throws Exception {
47 RequestMatcher csrfRequestMatcher = new RequestMatcher() {
48 private RegexRequestMatcher requestMatcher =
49 new RegexRequestMatcher("/api/", 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("/login**").permitAll()
62 .antMatchers("/manage/**").permitAll()
63 .antMatchers("/api/auth-info").permitAll()
64 .antMatchers("/api/**").authenticated()
65 .antMatchers("/management/health").permitAll()
66 .antMatchers("/management/info").permitAll()
67 .antMatchers("/management/prometheus").permitAll()
68 .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
69 .anyRequest().authenticated()//.and().oauth2ResourceServer().jwt()
70 .and()
71 .oauth2Login()
72 .redirectionEndpoint()
73 .baseUri("/oauth2**")
74 .and()
75 .failureUrl("/api/redirectToHome")
76 .userInfoEndpoint().userService(oauth2UserService())
77 ;
78 http.cors().disable();
79 }
80
81
82 private OAuth2UserService<OAuth2UserRequest, OAuth2User> 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("/tenant1/home")
102 public String home() {
103 return "tenant1Home";
104 }
105
106}
107@Controller
108public class Tenant2HomeController {
109
110 @GetMapping("/tenant2/home")
111 public String home() {
112 return "tenant2Home";
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("/login**").permitAll()
125 .antMatchers("/manage/**").permitAll()
126 .antMatchers("/api/auth-info").permitAll()
127 .antMatchers("/api/**").authenticated()
128 .antMatchers("/management/health").permitAll()
129 .antMatchers("/management/info").permitAll()
130 .antMatchers("/management/prometheus").permitAll()
131 .antMatchers("/management/**").hasAuthority("ADMIN")
132 .antMatchers("/tenant1/**").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("/tenant2/**"))
147 .csrf()
148 .disable()
149 .authorizeRequests()
150 .antMatchers("/tenant2/**").hasAuthority("BASIC_USER")
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("user")
160 .password("{noop}password")
161 .roles("BASIC_USER");
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...).
QUESTION
Prometheus kubelet metrics with pod labels
Asked 2021-Dec-03 at 10:41I 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:39As 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 metrickube_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="test"}
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.
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