Lors de l’installation d’un controller Kubernetes, il est possible que l’accès au endpoint /metrics
soit interdit:
$ curl -k https://<controller-ip>:8443/metrics
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/metrics\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
Un des cas les plus répandus est la récupération des métriques de composants du controlplane Kubernetes avec Prometheus.
Ici le controller nous identifie en tant qu’utilisateur anonyme system:anonymous
. Cela est dû au fait que nous faisons
un appel à l’API sans authentification, mais cela peut également arriver si nous utilisons un token JWT via un
ServiceAccount.
curl -k -H "Authorization: Bearer <jwt>" https://<controller-ip>:8443/metrics
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "forbidden: User \"system:serviceaccount:my-namespace:my-serviceaccountname\" cannot get path \"/metrics\"",
"reason": "Forbidden",
"details": {},
"code": 403
}
Ici notre token JWT est identifié comme étant celui du service account my-serviceaccountname
du namespace my-namespace
.
Lorsque cette erreur survient, l’API que vous interrogez est protégée par une revue de ses accès via le système RBAC de Kubernetes. Cette revue est soit faite en direct (dans le cadre de l’APIServer) ou via les SelfSubjectAccessReview (SSAR) (API).
Voici un résumé bref de ce qu’il va se passer en terme de flux au moment de l’appel à /metrics
:
Le endpoint /metrics
(tout comme /healthz
et /readyz
, par exemple) ne dessert aucune ressource Kubernetes, il
s’agit d’un endpoint spécifique au controller. Il sera donc impossible d’y avoir accès au travers d’un Role
,
vu que la notion de namespace n’existe pas pour les endpoints non liés à une ressource Kubernetes, mais en revanche
il est possible de créer un ClusterRole
qui autorisera l’accès à ce endpoint.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: controller-metrics
rules:
- apiGroups: [""]
nonResourceURLs: ["/metrics"]
verbs: ["get"]
Ensuite on associe ce ClusterRole
à un ClusterRoleBinding
:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: controller-metrics
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: controller-metrics
subjects:
- kind: ServiceAccount
name: my-serviceaccountname
namespace: my-namespace
Point important, comme il s’agit d’un ClusterRole, cela signifie que si vous accordez ce droit à un compte de service il pourra lire ce chemin sur toutes les API l’implémentant et utilisant le système RBAC de Kubernetes en SubjectAccessReview. C’est donc un droit à donner avec parcimonie.
Vous savez maintenant comment gérer ce cas d’erreur.