ProxyAuthK8S

Statut et Events

La condition Ready d'une ProxyKubeApi, ses codes de raison, ses Events et ses métriques de reconcile

Le controller publie l'état de chaque ProxyKubeApi sous une forme que les outils Kubernetes savent lire : une condition Ready, des Events sur la ressource et des métriques de reconcile (RFC 0011).

$ kubectl get proxykubeapis -n team-a
NAME    READY   REASON              AGE
prod    False   TargetUnreachable   3d
$ kubectl wait --for=condition=Ready proxykubeapi/prod -n team-a

kubectl wait, le health check d'Argo CD et celui de Flux lisent status.conditions.

La condition Ready

  • True avec la raison Reconciled : la cible répond, le cluster est servi.
  • False avec un code bloquant : status.error en porte le message.
  • observedGeneration n'avance que sur un succès : une CR en échec garde la génération de son dernier succès, ce qui dit « cette version de la spec n'a jamais été servie ».
  • lastTransitionTime ne bouge que quand le statut d'une condition change.

Chaque avis devient une condition True à côté de Ready, de type égal à son code.

Les codes

CodeSévéritéQuand
Reconciledsuccèsla cible répond, la CR est servie
InvalidSpecbloquantla spec est refusée par la validation du controller
OidcConfigUnresolvedbloquantle Secret de oidc_provider.config_from ne se lit pas
TargetUnreachablebloquantla sonde ne joint pas la cible
ProbeFailedbloquantla sonde échoue elle-même
CacheWriteFailedbloquantl'écriture (ou la suppression) dans Redis échoue
StatusWriteFailedbloquantle patch du statut échoue
FinalizerFailedbloquantl'ajout ou le retrait du finalizer échoue
RulesRestrictedavisdes règles changent de sens sous une restriction de ports, de verbes ou d'exec (status.warnings)
DeprecatedInsecureCertaviscert: Insecure, l'ancien nom de SystemRoots
Deletedavisle finalizer a retiré le cluster de Redis
AgentNoTunnelbloquantun cluster service: Agent dont aucun pod de la passerelle ne tient de tunnel (RFC 0012) ; le détail est dans status.agent
AgentLimitCappedavislimits.streams_per_tunnel dépasse agentGateway.limits.maxStreamsPerTunnel et y est ramené
AgentBootstrapNeededavisOneShotToken : aucun agent connecté et le jeton est consommé ou expiré (annoter proxyauth.weebo.si.rs/regenerate-bootstrap), ou il n'a pas pu être écrit
AgentVersionSkewavisun agent a plus d'une mineure de retard sur le proxy, est plus récent que lui, ou annonce une version qui n'est pas un SemVer ; ou la passerelle a refusé le protocole d'un agent alors que d'autres tunnels servent (RFC 0013)
AgentProtocolUnsupportedbloquantaucun tunnel, et la passerelle a refusé le protocole de l'agent dans les 5 dernières minutes : la cause de AgentNoTunnel ; le détail est dans status.agent.refused
UpstreamModeNotAllowedbloquantupstream_auth.mode hors de upstreamAuth.allowedModes du chart (RFC 0014) ; le proxy répond 503 à ce cluster, jamais en Passthrough
UpstreamModeUnsupportedbloquantupstream_auth.mode que cette version ne sert pas encore (RFC 0014, décision 34) ; 503, jamais en Passthrough
ClientCertMissingbloquantFrontProxy : le Secret proxyauth-frontproxy-<ns>.<nom> du namespace du proxy est absent, illisible, sans le label app.kubernetes.io/managed-by=proxyauthk8s, ou son certificat est expiré ou illisible ; status.upstreamAuth.clientCertSecret donne le nom
ClientCertTargetMismatchbloquantFrontProxy : l'annotation proxyauth.weebo.si.rs/front-proxy-target du Secret ne vaut pas status.upstreamAuth.clientCertTarget (certificat posé pour une autre cible)
ClientCertNameTooLongbloquantFrontProxy : proxyauth-frontproxy-<ns>.<nom> dépasse 253 caractères
ClientCertSubjectReservedbloquantFrontProxy : le CN ou l'O du certificat commence par system: ; utiliser un certificat dédié
AudienceValidationRequiredbloquantun mode de confiance alors que OIDC_AUDIENCE_VALIDATION n'est pas enforce
ClientCertExpiringavisle certificat FrontProxy expire dans moins de min(30 j, ⅓ de sa durée de vie)
FrontProxyNotReadyavisun cluster encore en Passthrough qui prépare FrontProxy (préfixes posés) ne serait pas servi une fois basculé ; le message dit pourquoi
UpstreamIdentityNotHonouredbloquantla sonde de confiance (SelfSubjectReview par le leader, chaque minute) voit une autre identité que celle affirmée : certificat d'une CA --client-ca-file, ou en-tête de groupe ou d'extra non lu ; le message nomme l'identité vue
FrontProxyNotTrustedbloquantla sonde de confiance reçoit 401 : la CA du certificat n'est pas dans --requestheader-client-ca-file, ou son CN pas dans --requestheader-allowed-names
UpstreamTrustUnknownavisla sonde de confiance n'a pas conclu (transport, 5xx, agent absent) ; le cluster reste servi
IssuerKeyUnavailablebloquantIssuer : le Secret proxyauth-issuer-<UID> du namespace du proxy est illisible, ne porte pas les labels du proxy (jamais adopté ni écrasé : le supprimer), ou ne peut pas être écrit ; le message le nomme
IssuerUrlMismatchbloquantIssuer : le chemin de issuer_key.issuer_url n'est pas /issuer/<ns>/<nom>, la route que le proxy sert
IssuerNotTrustedbloquantIssuer : la sonde reçoit 401 (issuer ou audience non déclarés dans l'AuthenticationConfiguration), ou l'apiserver accepte aussi une identité non préfixée (userValidationRules absentes)
IssuerNotReadyavisun cluster encore en Passthrough avec issuer_key ne serait pas servi une fois basculé en Issuer ; le message dit pourquoi
IssuerKeyRotationOverdueavisla clé Issuer n'a pas tourné depuis plus de rotation_days + 1 jours
IssuerBehindAgentavisIssuer derrière un agent : l'apiserver doit quand même joindre l'URL publique du proxy pour le JWKS
TokenExchangeAtRiskavisTokenExchange : l'IdP du cluster n'est pas celui du proxy et connector_id est vide, ou oidc_provider n'a pas de secret client (l'échange échouera le plus souvent) ; le message dit lequel, et il est aussi dans status.warnings

Le verdict de la sonde de confiance se suit aussi hors des conditions, succès compris : status.upstreamAuth.trust (Trusted, Rejected, NotHonoured, Unknown, Unguarded) et status.upstreamAuth.trustSince, colonne Trust en -o wide (Apiserver en front-proxy, Le proxy comme émetteur).

Les Events

  • Un Warning à chaque reconcile qui finit sur Ready: False, et à chaque erreur avant le statut (CacheWriteFailed, StatusWriteFailed, FinalizerFailed). Kubernetes les agrège en série : un échec répété fait monter un compteur, pas une liste.
  • Un Normal quand Ready passe à True ou change de raison, et pour chaque avis qui apparaît ou disparaît. Kubernetes regroupe les Events de même type et de même raison : la disparition d'un avis fait monter le compteur de l'Event de son apparition, sans en changer le message. La condition, elle, disparaît.
  • Un Normal Deleted quand le finalizer a nettoyé Redis.
$ kubectl describe proxykubeapi/prod -n team-a | sed -n '/Events/,$p'
  Type     Reason             From                       Message
  Warning  TargetUnreachable  proxy-kube-api-controller  Target service is not reachable

Seul le leader publie ; reportingInstance nomme son pod.

Une suppression attend Redis : si Redis ne répond pas, le finalizer reste et la ressource reste Terminating, avec un Warning CacheWriteFailed. Sans cela, le cluster supprimé resterait servi par le proxy, qui route depuis Redis.

Le rythme

AprèsProchain reconcile
un succès, ou un InvalidSpec5 min (±20 %)
un autre échec30 s, doublé à chaque nouvel échec, jusqu'à 5 min
un cluster service: Agent1 min au plus, pour que status.agent suive les tunnels

Une modification de la ressource déclenche un reconcile sans attendre. Le reconcile périodique rattrape ce que le watch ne voit pas : un Redis vidé, un Secret référencé modifié, une cible qui tombe ou revient. Un reconcile sans changement n'écrit rien sur la ressource.

Le watch du controller

Si le controller n'arrive plus à suivre les ProxyKubeApi (apiserver hôte injoignable, RBAC retiré), chaque erreur est journalisée. Après 5 minutes d'échec continu, /management/ready affiche "controller": "failing" dans son corps et la jauge proxyauth_controller_watch_failing passe à 1. Les sondes n'en dépendent pas : le proxy continue de servir les clusters déjà connus depuis Redis, et un redémarrage de toutes les réplicas n'y changerait rien.

Les métriques

/management/metrics expose :

  • proxyauth_reconcile_total{kind, result, reason} : result vaut success ou error, reason est un code du tableau ;
  • proxyauth_reconcile_duration_seconds{kind}.

Une alerte possible, par raison :

increase(proxyauth_reconcile_total{result="error"}[15m]) > 0

On this page