Cómo acceder a la API de su clúster de Kubernetes desde dentro de sus pods

logotipo de Kubernetes

La API de Kubernetes es su ruta para inspeccionar y administrar las operaciones de su clúster. Puede consumir la API mediante la CLI de Kubectl, herramientas como curlo la integración oficial bibliotecas para lenguajes de programación populares.

La API también está disponible para aplicaciones dentro de su clúster. Los pods de Kubernetes reciben automáticamente acceso a la API y pueden autenticarse mediante una cuenta de servicio proporcionada. Realiza interacciones consumiendo las variables de entorno inyectadas y los archivos de certificado para realizar conexiones desde el cliente de su elección.

¿Por qué acceder a la API de Kubernetes dentro de los pods?

Hay varios casos de uso para el acceso a la API en el pod. Esta técnica permite que las aplicaciones inspeccionen dinámicamente su entorno, apliquen cambios de Kubernetes y recopilen métricas del plano de control que brindan información sobre el rendimiento.

Algunas organizaciones desarrollan sus propias herramientas en torno a Kubernetes. Podrían implementar una aplicación especial en el clúster que use la API para exponer funciones adicionales. Operar desde dentro del clúster puede ser más seguro que realizar llamadas a la API desde un script externo, ya que no necesita abrir su entorno ni compartir cuentas de servicio y tokens de autenticación.

Uso de las bibliotecas de cliente de API

El método más sencillo y recomendado para acceder a la API de Kubernetes desde un pod es utilizar una biblioteca de cliente. Opciones totalmente compatibles están disponibles para C, .NET, Go, Haskell, Java, JavaScript, Perl, Python y Ruby. hay equivalentes soluciones mantenidas por la comunidad para la mayoría de los otros lenguajes de programación populares.

Las bibliotecas cliente tienen compatibilidad integrada para descubrir el entorno de clúster en el que se ejecutan. Cada implementación proporciona una función a la que puede llamar que configurará la biblioteca para conectarse al servidor de API correcto.

Este es un ejemplo de cómo enumerar los Pods en su clúster dentro de una aplicación de Python:

from kubernetes import client, config
 
config.load_incluster_config()
 
api = client.CoreV1Api()
 
# Perform necessary API interactions
# pods = api.list_pod_for_all_namespaces()

Es fácil trabajar con este enfoque y no requiere configuración manual. Sin embargo, a veces no podrá usar una biblioteca de cliente. En esos casos, aún es posible acceder manualmente a la API utilizando la cuenta de servicio que proporciona Kubernetes.

Realización de interacciones API manuales

Para llamar a la API, necesita saber dos cosas: el nombre de host en el clúster en el que está expuesto y el token de la cuenta de servicio que autenticará su Pod.

El nombre de host de la API siempre es kubernetes.default.svc. El proveedor de DNS de Kubernetes resolverá este nombre en el servidor API del plano de control. Como alternativa, puede utilizar el $KUBERNETES_SERVICE_HOST variable de entorno para descubrir la dirección IP del servidor API:

$ echo $KUBERNETES_SERVICE_HOST
10.96.0.1

La API solo está disponible a través de HTTPS. Puede encontrar el archivo de la autoridad de certificación para su clúster en /var/run/secrets/kubernetes.io/serviceaccount/ca.crt dentro de su Pod. Kubernetes deposita esto en el sistema de archivos cada vez que se crea un nuevo contenedor.

Deberá autenticarse para lograr algo útil con la API. Kubernetes crea un nuevo cuenta de servicio para cada Pod y proporciona su token en /var/run/secrets/kubernetes.io/serviceaccount/token. Esto debe incluirse con cada solicitud HTTP como un token de portador en el Authorization encabezamiento.

Poniendo todo junto, aquí hay un ejemplo de cómo hacer una solicitud API básica de Kubernetes en el Pod usando curl:

$ curl 
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 
  -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  https://kubernetes.default.svc/api
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.49.2:8443"
    }
  ]

El servidor de Kubernetes ha respondido con las versiones de API disponibles. Esto confirma que se ha realizado una conexión exitosa usando el kubernetes.default.svc nombre de host y la cuenta de servicio proporcionada.

Manejo de RBAC

Aunque una solicitud de API se haya realizado con éxito, la mayoría de los demás estarán fuera de los límites si RBAC está habilitado para su clúster. Las cuentas de servicio recién creadas no reciben roles automáticamente, por lo que su Pod no podrá solicitar puntos finales de API protegidos.

Puede resolver esto creando sus propios objetos de rol y vinculándolos a la cuenta de servicio que se proporciona a sus pods. Primero crea un nuevo Rol:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: demo-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list"]

Aplíquelo a su clúster con Kubectl:

$ kubectl apply -f role.yaml

A continuación, vincule el rol a la cuenta de servicio:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: demo-role-binding
subjects:
  - kind: ServiceAccount
    name: default
    apiGroup: ""
roleRef:
  kind: Role
  name: demo-role
  apiGroup: ""

los default la cuenta de servicio se selecciona como el asunto del enlace de roles. Los pods siempre se suministran con esta cuenta de servicio, en el ámbito del espacio de nombres en el que se crearon. En este ejemplo, el default se usa el espacio de nombres, pero esto debe cambiarse en los objetos Role y RoleBinding si su Pod existe en un espacio de nombres diferente.

Agregue RoleBinding a su clúster:

$ kubectl apply -f role-binding.yaml

Ahora sus Pods podrán obtener y enumerar otros objetos Pod en el default espacio de nombres Puede verificar esto haciendo una solicitud de API al punto final de Pods con espacio de nombres:

$ curl 
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 
  -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  https://kubernetes.default.svc/api/v1/namespaces/default/pods
{
  "kind": "PodList",
  "apiVersion": "v1"
  ...
}

Los pods pueden identificar su propio espacio de nombres leyendo el /var/run/secrets/kubernetes.io/serviceaccount/namespace expediente:

$ cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
default

Esto proporciona un método conveniente para interpolar el espacio de nombres activo en las URL de punto final:

$ curl 
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 
  -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
  https://kubernetes.default.svc/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods
{
  "kind": "PodList",
  "apiVersion": "v1"
  ...
}

Elegir una cuenta de servicio diferente

Kubernetes proporciona automáticamente a los Pods la default cuenta de servicio dentro de su espacio de nombres. Opcionalmente, puede inyectar una cuenta de servicio diferente configurando el spec.serviceAccountName campo en sus Pods:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  serviceAccountName: demo-sa

En este ejemplo, el Pod se autenticará como el demo-sa simbólico. Puede crear esta cuenta de servicio manualmente y vincularla a los roles que necesite.

$ kubernetes create serviceaccount demo-sa

La cuenta de servicio debe existir en el mismo espacio de nombres que el Pod.

Cancelación del montaje de la cuenta de servicio

La inyección automática de cuentas de servicio no siempre es deseable. Puede ser un peligro para la seguridad, ya que un Pod comprometido exitoso ofrece acceso inmediato a la API de su clúster de Kubernetes. Puede deshabilitar los montajes de tokens de cuenta de servicio con el spec.automountServiceAccountToken Campo de manifiesto de pod:

apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  automountServiceAccountToken: false

Kubernetes no inyectará el /var/run/secrets/kubernetes.io/serviceaccount/token expediente. Esto evitará que el Pod se autentique en la API de Kubernetes, a menos que proporcione las credenciales manualmente con un método diferente. Este campo también es compatible con los objetos de la cuenta de servicio, lo que los hace inelegibles para montarse automáticamente en cualquier Pod.

Si usa el montaje de cuentas de servicio, configure las políticas RBAC apropiadas para restringir el token a sus casos de uso previstos. Evitar el acceso altamente privilegiado disminuirá el riesgo de daños en caso de que un atacante obtenga acceso a su Pod.

Resumen

Acceder al servidor API de Kubernetes desde dentro de su clúster permite que las aplicaciones en ejecución inspeccionen y modifiquen las cargas de trabajo vecinas. Puede agregar funciones adicionales sin abrir su clúster al acceso a la API externa.

Las bibliotecas de clientes oficiales facilitan la puesta en marcha, si son adecuadas para su caso de uso. En otras situaciones, deberá realizar solicitudes manualmente a https://kubernetes.default.svc, proporcionando el archivo de la autoridad de certificación y el token de la cuenta de servicio que Kubernetes inyecta en sus contenedores Pod. Independientemente del enfoque que utilice, la cuenta de servicio debe estar configurada correctamente con enlaces de roles RBAC para que el pod tenga permiso para realizar las acciones previstas.

Deja un comentario

En esta web usamos cookies para personalizar tu experiencia de usuario.    Política de cookies
Privacidad