mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['src/pentesting-cloud/kubernetes-security/kubernetes-basics.
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Hay **diferentes formas de exponer services** en Kubernetes para que tanto los endpoints **internal** como los endpoints **external** puedan acceder a ellos. Esta configuración de Kubernetes es bastante crítica, ya que el administrator podría dar acceso a **attackers a services they shouldn't be able to access**.
|
||||
Hay **diferentes formas de exponer servicios** en Kubernetes para que tanto los endpoints **internos** como los endpoints **externos** puedan acceder a ellos. Esta configuración de Kubernetes es bastante crítica, ya que el administrador podría dar acceso a **atacantes a servicios a los que no deberían poder acceder**.
|
||||
|
||||
### Automatic Enumeration
|
||||
|
||||
Antes de empezar a enumerar las formas que K8s ofrece para exponer services al público, ten en cuenta que si puedes listar namespaces, services e ingresses, puedes encontrar todo lo expuesto al público con:
|
||||
Antes de empezar a enumerar las formas que K8s ofrece para exponer servicios al público, ten en cuenta que si puedes listar namespaces, services e ingresses, puedes encontrar todo lo expuesto al público con:
|
||||
```bash
|
||||
kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
|
||||
echo "Namespace: $ns"
|
||||
@@ -20,13 +20,13 @@ done | grep -v "ClusterIP"
|
||||
```
|
||||
### ClusterIP
|
||||
|
||||
Un servicio **ClusterIP** es el **service** predeterminado de Kubernetes. Te da un **service inside** tu cluster al que otras apps dentro de tu cluster pueden acceder. **No hay acceso externo**.
|
||||
Un **ClusterIP** service es el **default** Kubernetes **service**. Te da un **service dentro de** tu cluster que otras apps dentro de tu cluster pueden acceder. **No hay acceso externo**.
|
||||
|
||||
Sin embargo, esto se puede acceder usando el Kubernetes Proxy:
|
||||
Sin embargo, esto puede ser accedido usando el Kubernetes Proxy:
|
||||
```bash
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
Ahora, puedes navegar a través de la Kubernetes API para acceder a services usando este esquema:
|
||||
Ahora, puedes navegar a través de la API de Kubernetes para acceder a servicios usando este esquema:
|
||||
|
||||
`http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/`
|
||||
|
||||
@@ -34,7 +34,7 @@ Por ejemplo, podrías usar la siguiente URL:
|
||||
|
||||
`http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/`
|
||||
|
||||
para acceder a este service:
|
||||
para acceder a este servicio:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -50,7 +50,7 @@ port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
```
|
||||
_Este método requiere que ejecutes `kubectl` como un **authenticated user**._
|
||||
_Este método requiere que ejecutes `kubectl` como un **usuario autenticado**._
|
||||
|
||||
Lista todos los ClusterIPs:
|
||||
```bash
|
||||
@@ -58,7 +58,7 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam
|
||||
```
|
||||
### NodePort
|
||||
|
||||
Cuando se utiliza **NodePort**, se pone a disposición un puerto designado en todos los Nodes (que representan las Virtual Machines). El **tráfico** dirigido a este puerto específico se **redirige al service** de forma sistemática. Normalmente, este método no se recomienda debido a sus inconvenientes.
|
||||
Cuando se utiliza **NodePort**, se pone a disposición un puerto designado en todos los Nodes (que representan las Virtual Machines). El **tráfico** dirigido a este puerto específico se **enruta al service** de forma sistemática. Por lo general, este método no se recomienda debido a sus inconvenientes.
|
||||
|
||||
List all NodePorts:
|
||||
```bash
|
||||
@@ -83,11 +83,22 @@ protocol: TCP
|
||||
```
|
||||
Si **no especificas** el **nodePort** en el yaml (es el puerto que se abrirá), se usará un puerto en el **rango 30000–32767**.
|
||||
|
||||
Al revisar Services NodePort o LoadBalancer, inspecciona también los campos traffic-policy porque cambian qué nodos y backends son útiles desde una fuente dada:
|
||||
```bash
|
||||
kubectl get services --all-namespaces \
|
||||
-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,ETP:.spec.externalTrafficPolicy,ITP:.spec.internalTrafficPolicy,AFFINITY:.spec.sessionAffinity,DIST:.spec.trafficDistribution,NODEPORTS:.spec.ports[*].nodePort'
|
||||
```
|
||||
- `externalTrafficPolicy: Local` preserva la IP de origen original del cliente para el tráfico de NodePort/LoadBalancer y evita reenviar a endpoints en otros nodos. Un nodo sin un endpoint local listo puede descartar el tráfico incluso si el Service tiene endpoints en otro lugar.
|
||||
- `externalTrafficPolicy: Cluster` es el valor predeterminado y puede reenviar a través de cualquier nodo, pero los logs del backend pueden ver IPs de nodo en lugar de la IP externa real del cliente.
|
||||
- `internalTrafficPolicy: Local` limita el tráfico del Service dentro del cluster a endpoints locales al nodo de origen. Esto es routing por localidad, no un boundary de autorización.
|
||||
- `sessionAffinity: ClientIP` puede hacer que pruebas repetidas desde un cliente lleguen al mismo backend, ocultando otros endpoints listos durante comprobaciones manuales.
|
||||
- `trafficDistribution` y los EndpointSlice topology hints pueden preferir endpoints de la misma zona o del mismo nodo en clusters más nuevos; trátalos como preferencias de routing y no como una política de seguridad estricta.
|
||||
|
||||
### LoadBalancer
|
||||
|
||||
Expone el Service externamente **using a cloud provider's load balancer**. En GKE, esto iniciará un [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) que te dará una única dirección IP que reenviará todo el tráfico a tu service. En AWS, lanzará un Load Balancer.
|
||||
Expone el Service externamente **usando un load balancer del cloud provider**. En GKE, esto levantará un [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) que te dará una sola dirección IP que reenviará todo el tráfico a tu service. En AWS lanzará un Load Balancer.
|
||||
|
||||
Tienes que pagar por un LoadBalancer por cada service expuesto, lo cual puede ser costoso.
|
||||
Tienes que pagar por un LoadBalancer por cada service expuesto, lo que puede ser costoso.
|
||||
|
||||
List all LoadBalancers:
|
||||
```bash
|
||||
@@ -96,15 +107,15 @@ kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.nam
|
||||
### External IPs
|
||||
|
||||
> [!TIP]
|
||||
> Los External IPs son expuestos por servicios de tipo Load Balancers y generalmente se usan cuando se está utilizando un external Cloud Provider Load Balancer.
|
||||
> External IPs son expuestos por services de tipo Load Balancers y generalmente se usan cuando se está utilizando un external Cloud Provider Load Balancer.
|
||||
>
|
||||
> Para encontrarlos, revisa los load balancers con valores en el campo `EXTERNAL-IP`.
|
||||
|
||||
El tráfico que ingresa al cluster con la **external IP** (como **destination IP**), en el puerto del Service, será **ruteado a uno de los endpoints del Service**. `externalIPs` no están gestionados por Kubernetes y son responsabilidad del administrador del cluster.
|
||||
El tráfico que ingresa al cluster con la **external IP** (como **destination IP**), en el puerto del Service, será **enrutado a uno de los Service endpoints**. `externalIPs` no son administrados por Kubernetes y son responsabilidad del administrador del cluster.
|
||||
|
||||
`externalIPs` es un campo sensible de control de ruta porque un usuario que pueda configurarlo podría reclamar tráfico para una dirección IP que el propietario del Service no debería controlar si la red circundante enruta esa IP al cluster. Kubernetes anunció la deprecación y eliminación planificada de `externalIPs` de Service en v1.36, así que es preferible usar mecanismos de exposición gestionados por el controller como integraciones de LoadBalancer o Gateway API cuando sea posible, y restringir/admitir este campo con cuidado mientras todavía exista.
|
||||
`externalIPs` es un campo sensible de control de rutas porque un usuario que pueda configurarlo podría reclamar tráfico para una dirección IP que el propietario del Service no debería controlar si la red circundante enruta esa IP al cluster. Kubernetes anunció la deprecación y eliminación planificada de `externalIPs` de Service en v1.36, así que es preferible usar mecanismos de exposición controlados por controller, como integraciones de LoadBalancer o Gateway API cuando sea posible, y restringir/permitir este campo con cuidado mientras aún exista.
|
||||
|
||||
En la spec del Service, `externalIPs` puede especificarse junto con cualquiera de los `ServiceTypes`. En el ejemplo de abajo, "`my-service`" puede ser accedido por clients en "`80.11.12.10:80`" (`externalIP:port`)
|
||||
En la Service spec, `externalIPs` puede especificarse junto con cualquiera de los `ServiceTypes`. En el ejemplo de abajo, "`my-service`" puede ser accedido por clientes en "`80.11.12.10:80`" (`externalIP:port`)
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -123,9 +134,9 @@ externalIPs:
|
||||
```
|
||||
### ExternalName
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Los Services de tipo ExternalName **asignan un Service a un nombre DNS**, no a un selector típico como `my-service` o `cassandra`. Especificas estos Services con el parámetro `spec.externalName`.
|
||||
[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Los Services de tipo ExternalName **mapean un Service a un nombre DNS**, no a un selector típico como `my-service` o `cassandra`. Especificas estos Services con el parámetro `spec.externalName`.
|
||||
|
||||
Esta definición de Service, por ejemplo, asigna el Service `my-service` en el namespace `prod` a `my.database.example.com`:
|
||||
Esta definición de Service, por ejemplo, mapea el Service `my-service` en el namespace `prod` a `my.database.example.com`:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
@@ -136,7 +147,7 @@ spec:
|
||||
type: ExternalName
|
||||
externalName: my.database.example.com
|
||||
```
|
||||
Al buscar el host `my-service.prod.svc.cluster.local`, el DNS Service del cluster devuelve un registro `CNAME` con el valor `my.database.example.com`. Acceder a `my-service` funciona de la misma manera que con otros Services, pero con la diferencia crucial de que la **redirección ocurre a nivel de DNS** en lugar de mediante proxying o forwarding.
|
||||
Al buscar el host `my-service.prod.svc.cluster.local`, el cluster DNS Service devuelve un registro `CNAME` con el valor `my.database.example.com`. Acceder a `my-service` funciona de la misma manera que otros Services, pero con la diferencia crucial de que **la redirección ocurre a nivel de DNS** en lugar de mediante proxying o forwarding.
|
||||
|
||||
List all ExternalNames:
|
||||
```bash
|
||||
@@ -144,24 +155,24 @@ kubectl get services --all-namespaces | grep ExternalName
|
||||
```
|
||||
### EndpointSlices
|
||||
|
||||
EndpointSlices muestran las direcciones y puertos de backend concretos a los que un Service enruta actualmente. Son especialmente útiles cuando un Service no tiene selector, cuando las etiquetas no explican el flujo de tráfico, o cuando solo algunos backends están listos.
|
||||
EndpointSlices muestran las direcciones y puertos concretos de backend a los que un Service enruta actualmente. Son especialmente útiles cuando un Service no tiene selector, cuando las labels no explican el camino del tráfico, o cuando solo algunos backends están ready.
|
||||
|
||||
Lista de EndpointSlices asociados con Services:
|
||||
List EndpointSlices associated with Services:
|
||||
```bash
|
||||
kubectl get endpointslices --all-namespaces
|
||||
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-name> -o yaml
|
||||
kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service-name> \
|
||||
-o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port'
|
||||
```
|
||||
Al revisar la exposición, compara el selector del Service con el `targetRef` de EndpointSlice, las direcciones de endpoint, las condiciones de readiness y los ports. Un Service sin selector puede emparejarse con EndpointSlices gestionados manualmente y enrutar tráfico a destinos que no son Pods o inesperados.
|
||||
Al revisar la exposición, compara el selector del Service con el `targetRef` de EndpointSlice, las direcciones de endpoint, las condiciones de readiness y los ports. Un Service sin selector puede emparejarse con EndpointSlices gestionados manualmente y dirigir tráfico a destinos que no sean Pods o inesperados.
|
||||
|
||||
### Ingress
|
||||
|
||||
A diferencia de todos los ejemplos anteriores, **Ingress NO es un tipo de service**. En su lugar, se sitúa **frente a múltiples services y actúa como un “smart router”** o punto de entrada a tu cluster.
|
||||
A diferencia de todos los ejemplos anteriores, **Ingress NO es un tipo de service**. En su lugar, se sitúa **delante de múltiples services y actúa como un “smart router”** o punto de entrada a tu cluster.
|
||||
|
||||
Puedes hacer muchas cosas distintas con un Ingress, y hay **muchos tipos de Ingress controllers que tienen distintas capacidades**.
|
||||
Puedes hacer muchas cosas diferentes con un Ingress, y hay **muchos tipos de Ingress controllers que tienen diferentes capacidades**.
|
||||
|
||||
El Ingress controller predeterminado de GKE levantará un [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) para ti. Esto te permitirá hacer tanto routing basado en paths como basado en subdomains hacia backend services. Por ejemplo, puedes enviar todo lo que llegue a foo.yourdomain.com al service foo, y todo lo que esté bajo la ruta yourdomain.com/bar/ al service bar.
|
||||
El controlador de ingress predeterminado de GKE levantará un [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) para ti. Esto te permitirá hacer routing basado tanto en path como en subdomain hacia backend services. Por ejemplo, puedes enviar todo lo que vaya a foo.yourdomain.com al service foo, y todo lo que esté bajo la ruta yourdomain.com/bar/ al service bar.
|
||||
|
||||
El YAML para un objeto Ingress en GKE con un [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) podría verse así:
|
||||
```yaml
|
||||
@@ -197,19 +208,19 @@ name: bar
|
||||
port:
|
||||
number: 8080
|
||||
```
|
||||
Enumera todos los ingress:
|
||||
Lista todos los ingresses:
|
||||
```bash
|
||||
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'
|
||||
```
|
||||
Aunque en este caso es mejor obtener la info de cada uno por separado para leerla mejor:
|
||||
Aunque en este caso es mejor obtener la información de cada uno por separado para leerla mejor:
|
||||
```bash
|
||||
kubectl get ingresses --all-namespaces -o=yaml
|
||||
```
|
||||
### Gateway API
|
||||
|
||||
Gateway API es la nueva API de Kubernetes para exponer Services. Separa los objetos Gateway, propiedad de la infraestructura, de los objetos Route, propiedad de la aplicación, como HTTPRoute. Esto es útil para delegación, pero también significa que la exposición puede dividirse entre namespaces.
|
||||
Gateway API es la API más nueva de Kubernetes para exponer Services. Separa los objetos Gateway, propiedad de la infraestructura, de los objetos Route, propiedad de la aplicación, como HTTPRoute. Esto es útil para la delegación, pero también significa que la exposición puede dividirse entre namespaces.
|
||||
|
||||
Listar objetos de exposición de Gateway API:
|
||||
Lista los objetos de exposición de Gateway API:
|
||||
```bash
|
||||
kubectl get gatewayclasses
|
||||
kubectl get gateways --all-namespaces
|
||||
@@ -217,13 +228,16 @@ kubectl get httproutes --all-namespaces
|
||||
kubectl get gateway -n <namespace> <gateway-name> -o yaml
|
||||
kubectl get httproute -n <namespace> <route-name> -o yaml
|
||||
```
|
||||
Revisa los listeners de Gateway, los namespaces de rutas permitidos, `parentRefs` de Route, hostnames, filters, referencias a backend y condiciones de estado, como si la route fue accepted. Una Route accepted por un shared Gateway puede exponer un backend incluso cuando no existe ningún objeto legacy Ingress.
|
||||
Revisa los listeners de Gateway, los namespaces de rutas permitidos, `parentRefs` de Route, hostnames, filters, backend references y condiciones de estado como si la route fue aceptada. Una Route aceptada por un shared Gateway puede exponer un backend incluso cuando no existe ningún objeto legacy Ingress.
|
||||
|
||||
### References
|
||||
|
||||
- [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0)
|
||||
- [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/)
|
||||
- [https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/](https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/)
|
||||
- [https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/)
|
||||
- [https://kubernetes.io/docs/tutorials/services/source-ip/](https://kubernetes.io/docs/tutorials/services/source-ip/)
|
||||
- [https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/)
|
||||
- [https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/)
|
||||
- [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/)
|
||||
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
|
||||
**El autor original de esta página es** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(lee su publicación original** [**aquí**](https://sickrov.github.io)**)**
|
||||
|
||||
## Arquitectura & Basics
|
||||
## Architecture & Basics
|
||||
|
||||
### ¿Qué hace Kubernetes?
|
||||
### What does Kubernetes do?
|
||||
|
||||
- Permite ejecutar container/s en un container engine.
|
||||
- Schedule permite containers de forma eficiente.
|
||||
- Schedule permite que los containers cumplan su misión de forma eficiente.
|
||||
- Mantiene los containers activos.
|
||||
- Permite comunicaciones entre containers.
|
||||
- Permite deployment techniques.
|
||||
- Maneja volúmenes de información.
|
||||
- Gestiona volúmenes de información.
|
||||
|
||||
### Arquitectura
|
||||
### Architecture
|
||||
|
||||

|
||||
|
||||
@@ -24,45 +24,47 @@
|
||||
- **Service**: Cada pod tiene 1 **dirección IP** interna del rango interno del node. Sin embargo, también puede exponerse mediante un service. El **service también tiene una dirección IP** y su objetivo es mantener la comunicación entre pods, de modo que si uno muere, el **nuevo reemplazo** (con una IP interna diferente) **será accesible** expuesto en la **misma IP del service**. Puede configurarse como interno o externo. El service también actúa como un **load balancer cuando 2 pods están conectados** al mismo service.\
|
||||
Cuando se **crea un service** puedes encontrar los endpoints de cada service ejecutando `kubectl get endpoints`
|
||||
- **Kubelet**: agente principal del node. El componente que establece la comunicación entre node y kubectl, y solo puede ejecutar pods (a través del API server). El kubelet no gestiona containers que no hayan sido creados por Kubernetes.
|
||||
- **Kube-proxy**: es el service encargado de las comunicaciones (services) entre el apiserver y el node. La base es IPtables para nodes. Los usuarios más experimentados podrían instalar otros kube-proxies de otros vendors.
|
||||
- **Sidecar container**: Los sidecar containers son los containers que deben ejecutarse junto con el container principal en el pod. Este patrón sidecar extiende y mejora la funcionalidad de los containers actuales sin cambiarlos. Hoy en día, sabemos que usamos la tecnología de containers para envolver todas las dependencias necesarias para que la aplicación se ejecute en cualquier lugar. Un container hace solo una cosa y la hace muy bien.
|
||||
- **Kube-proxy**: es el service encargado de las comunicaciones (services) entre el apiserver y el node. La base es un IPtables para nodes. Los usuarios más experimentados podrían instalar otros kube-proxies de otros proveedores.
|
||||
- **Sidecar container**: Los sidecar containers son los containers que deben ejecutarse junto con el container principal en el pod. Este patrón sidecar amplía y mejora la funcionalidad de los containers actuales sin cambiarlos. Hoy en día, sabemos que usamos la tecnología de containers para envolver todas las dependencias de la aplicación y que pueda ejecutarse en cualquier lugar. Un container solo hace una cosa y la hace muy bien.
|
||||
- **Master process:**
|
||||
- **Api Server:** Es la forma en que los usuarios y los pods usan para comunicarse con el master process. Solo deberían permitirse solicitudes autenticadas.
|
||||
- **Scheduler**: Scheduling se refiere a asegurarse de que los Pods se asignen a Nodes para que Kubelet pueda ejecutarlos. Tiene suficiente inteligencia para decidir qué node tiene más recursos disponibles y asignar el nuevo pod a él. Ten en cuenta que el scheduler no inicia nuevos pods, solo se comunica con el proceso Kubelet que se ejecuta dentro del node, que lanzará el nuevo pod.
|
||||
- **Kube Controller manager**: Comprueba recursos como replica sets o deployments para verificar si, por ejemplo, se está ejecutando el número correcto de pods o nodes. En caso de que falte un pod, se comunicará con el scheduler para iniciar uno nuevo. Controla la replicación, tokens y servicios de cuenta hacia el API.
|
||||
- **etcd**: Almacenamiento de datos, persistente, consistente y distribuido. Es la base de datos de Kubernetes y el almacenamiento key-value donde mantiene el estado completo de los clusters (cada cambio se registra aquí). Componentes como el Scheduler o el Controller manager dependen de estos datos para saber qué cambios han ocurrido (recursos disponibles de los nodes, número de pods en ejecución...)
|
||||
- **Cloud controller manager**: Es el controller específico para flow controls y applications, i.e: si tienes clusters en AWS o OpenStack.
|
||||
- **Api Server:** Es la forma en que los usuarios y los pods usan para comunicarse con el master process. Solo deberían permitirse requests autenticadas.
|
||||
- **Scheduler**: Scheduling se refiere a asegurarse de que los Pods se asignen a Nodes para que Kubelet pueda ejecutarlos. Tiene suficiente inteligencia para decidir qué node tiene más recursos disponibles y asignarle el nuevo pod. Ten en cuenta que el scheduler no inicia nuevos pods, solo se comunica con el proceso Kubelet que se ejecuta dentro del node, el cual lanzará el nuevo pod.
|
||||
- **Kube Controller manager**: Comprueba recursos como replica sets o deployments para verificar, por ejemplo, si se está ejecutando el número correcto de pods o nodes. En caso de que falte un pod, se comunicará con el scheduler para iniciar uno nuevo. Controla la replicación, tokens y account services para el API.
|
||||
- **etcd**: Almacenamiento de datos, persistente, consistente y distribuido. Es la base de datos de Kubernetes y el almacenamiento key-value donde mantiene el estado completo de los clusters (cada cambio se registra aquí). Componentes como el Scheduler o el Controller manager dependen de estos datos para saber qué cambios han ocurrido (available resourced of the nodes, number of pods running...)
|
||||
- **Cloud controller manager**: Es el controller específico para flow controls y applications, es decir: si tienes clusters en AWS o OpenStack.
|
||||
|
||||
Ten en cuenta que, como puede haber varios nodes (ejecutando varios pods), también puede haber varios master processes cuyo acceso al Api server está load balanced y cuyo etcd está sincronizado.
|
||||
Ten en cuenta que, como puede haber varios nodes (ejecutando varios pods), también puede haber varios master processes cuyos accesos al Api server estén load balanced y cuyo etcd esté sincronizado.
|
||||
|
||||
**Volumes:**
|
||||
|
||||
Cuando un pod crea datos que no deberían perderse cuando el pod desaparezca, deberían almacenarse en un physical volume. **Kubernetes permite adjuntar un volume a un pod para persistir los datos**. El volume puede estar en la máquina local o en un **remote storage**. Si ejecutas pods en diferentes physical nodes, deberías usar un remote storage para que todos los pods puedan acceder a él.
|
||||
Cuando un pod crea datos que no deberían perderse cuando el pod desaparezca, deberían almacenarse en un physical volume. **Kubernetes allow to attach a volume to a pod to persist the data**. El volume puede estar en la máquina local o en un **remote storage**. Si ejecutas pods en diferentes physical nodes, deberías usar un remote storage para que todos los pods puedan acceder a él.
|
||||
|
||||
Kubernetes también soporta **image volumes** en versiones recientes. Un `image` volume monta una OCI image o artifact como una fuente de filesystem **read-only** dentro del Pod, usando campos como `volumes[].image.reference` y `volumes[].image.pullPolicy`. El kubelet descarga el artifact con las mismas credential sources usadas para container images, incluyendo node credentials, Pod `imagePullSecrets` y ServiceAccount `imagePullSecrets`. Durante una security review, trata los image volumes como runtime inputs y supply-chain dependencies: comprueba si la referencia está fijada por digest, qué registry credentials pueden obtenerla, dónde se monta y si `subPath` limita el directorio visible.
|
||||
|
||||
**Other configurations:**
|
||||
|
||||
- **ConfigMap**: Puedes configurar **URLs** para acceder a services. El pod obtendrá datos de aquí para saber cómo comunicarse con el resto de los services (pods). ¡Ten en cuenta que este no es el lugar recomendado para guardar credenciales!
|
||||
- **Secret**: Este es el lugar para **almacenar datos secretos** como passwords, API keys... codificados en B64. El pod podrá acceder a estos datos para usar las credenciales requeridas.
|
||||
- **Deployments**: Aquí se indican los componentes que serán ejecutados por kubernetes. Normalmente un usuario no trabajará directamente con pods, los pods se abstraen en **ReplicaSets** (número de los mismos pods replicados), que se ejecutan mediante deployments. Ten en cuenta que los deployments son para aplicaciones **stateless**. La configuración mínima para un deployment es el nombre y la image a ejecutar.
|
||||
- **StatefulSet**: Este component está pensado específicamente para applications como **databases** que necesitan **acceder al mismo storage**.
|
||||
- **Ingress**: Esta es la configuración que se usa para **exponer la application públicamente con una URL**. Ten en cuenta que esto también puede hacerse usando external services, pero esta es la forma correcta de exponer la application.
|
||||
- Si implementas un Ingress necesitarás crear **Ingress Controllers**. El Ingress Controller es un **pod** que será el endpoint que recibirá las requests y las comprobará, y las load balanceará hacia los services. El ingress controller **enviará la request según las ingress rules configuradas**. Ten en cuenta que las ingress rules pueden apuntar a diferentes paths o incluso subdomains hacia diferentes internal kubernetes services.
|
||||
- Una mejor práctica de seguridad sería usar un cloud load balancer o un proxy server como entrypoint para no tener ninguna parte del cluster de Kubernetes expuesta.
|
||||
- Cuando se recibe una request que no coincide con ninguna ingress rule, el ingress controller la dirigirá al "**Default backend**". Puedes `describe` el ingress controller para obtener la address de este parámetro.
|
||||
- **ConfigMap**: Puedes configurar **URLs** para acceder a services. El pod obtendrá datos de aquí para saber cómo comunicarse con el resto de services (pods). Ten en cuenta que este no es el lugar recomendado para guardar credentials.
|
||||
- **Secret**: Este es el lugar para **almacenar datos secretos** como passwords, API keys... codificados en B64. El pod podrá acceder a estos datos para usar las credentials requeridas.
|
||||
- **Deployments**: Aquí se indican los componentes que kubernetes debe ejecutar. Normalmente un usuario no trabajará directamente con pods, los pods se abstraen en **ReplicaSets** (número de mismos pods replicados), que se ejecutan mediante deployments. Ten en cuenta que los deployments son para aplicaciones **stateless**. La configuración mínima para un deployment es el name y la image a ejecutar.
|
||||
- **StatefulSet**: Este componente está pensado específicamente para aplicaciones como **databases** que necesitan **acceder al mismo storage**.
|
||||
- **Ingress**: Esta es la configuración que se usa para **exponer la aplicación públicamente con una URL**. Ten en cuenta que esto también puede hacerse usando external services, pero esta es la forma correcta de exponer la aplicación.
|
||||
- Si implementas un Ingress necesitarás crear **Ingress Controllers**. El Ingress Controller es un **pod** que será el endpoint que recibirá las requests y las comprobará y las load balanceará hacia los services. el ingress controller **enviará la request según las ingress rules configuradas**. Ten en cuenta que las ingress rules pueden apuntar a diferentes paths o incluso subdomains a diferentes internal kubernetes services.
|
||||
- Una mejor práctica de seguridad sería usar un cloud load balancer o un proxy server como entrypoint para no tener ninguna parte del Kubernetes cluster expuesta.
|
||||
- Cuando se recibe una request que no coincide con ninguna ingress rule, el ingress controller la dirigirá al "**Default backend**". Puedes usar `describe` sobre el ingress controller para obtener la dirección de este parámetro.
|
||||
- `minikube addons enable ingress`
|
||||
|
||||
### PKI infrastructure - Certificate Authority CA:
|
||||
|
||||

|
||||
|
||||
- CA es la raíz de confianza para todos los certificates dentro del cluster.
|
||||
- Permite que los componentes se validen entre sí.
|
||||
- CA is the trusted root for all certificates inside the cluster.
|
||||
- Permite que los components se validen entre sí.
|
||||
- Todos los certificates del cluster están firmados por la CA.
|
||||
- ETCd tiene su propio certificate.
|
||||
- types:
|
||||
- apiserver cert.
|
||||
- kubelet cert.
|
||||
- scheduler cert.
|
||||
- tipos:
|
||||
- cert de apiserver.
|
||||
- cert de kubelet.
|
||||
- cert de scheduler.
|
||||
|
||||
## Basic Actions
|
||||
|
||||
@@ -105,7 +107,7 @@ $ minikube delete
|
||||
```
|
||||
### Kubectl Basics
|
||||
|
||||
**`Kubectl`** es la herramienta de línea de comandos para clusters de kubernetes. Se comunica con el Api server del proceso master para realizar acciones en kubernetes o para pedir datos.
|
||||
**`Kubectl`** es la herramienta de línea de comandos para clusters de kubernetes. Se comunica con el Api server del proceso master para realizar acciones en kubernetes o solicitar datos.
|
||||
```bash
|
||||
kubectl version #Get client and server version
|
||||
kubectl get pod
|
||||
@@ -136,7 +138,7 @@ kubectl delete deployment mongo-depl
|
||||
#Deploy from config file
|
||||
kubectl apply -f deployment.yml
|
||||
```
|
||||
### Dashboard de Minikube
|
||||
### Minikube Dashboard
|
||||
|
||||
El dashboard te permite ver más fácilmente qué está ejecutando minikube; puedes encontrar la URL para acceder en:
|
||||
```
|
||||
@@ -154,11 +156,11 @@ http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kube
|
||||
### Ejemplos de archivos de configuración YAML
|
||||
|
||||
Cada archivo de configuración tiene 3 partes: **metadata**, **specification** (qué necesita ser lanzado), **status** (estado deseado).\
|
||||
Dentro de la specification del archivo de configuración de deployment puedes encontrar la plantilla definida con una nueva estructura de configuración que define la image a ejecutar:
|
||||
Dentro de la specification del archivo de configuración del deployment puedes encontrar la template definida con una nueva configuración structure que define la image a ejecutar:
|
||||
|
||||
**Ejemplo de Deployment + Service declarados en el mismo archivo de configuración (from** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**
|
||||
|
||||
Como un service normalmente está relacionado con un deployment, es posible declarar ambos en el mismo archivo de configuración (el service declarado en esta config solo es accesible internamente):
|
||||
Como un service suele estar relacionado con un deployment, es posible declarar ambos en el mismo archivo de configuración (el service declarado en esta config solo es accesible internamente):
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
@@ -225,7 +227,7 @@ targetPort: 8081
|
||||
nodePort: 30000
|
||||
```
|
||||
> [!NOTE]
|
||||
> Esto es útil para pruebas, pero para producción deberías tener solo servicios internos y un Ingress para exponer la aplicación.
|
||||
> Esto es útil para testing, pero para producción deberías tener solo servicios internos y un Ingress para exponer la aplicación.
|
||||
|
||||
**Ejemplo de archivo de configuración de Ingress**
|
||||
|
||||
@@ -247,7 +249,7 @@ servicePort: 80
|
||||
```
|
||||
**Ejemplo de archivo de configuración de secrets**
|
||||
|
||||
Observa cómo las passwords están codificadas en B64 (¡lo cual no es seguro!)
|
||||
Observa cómo las contraseñas están codificadas en B64 (¡lo cual no es seguro!)
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
@@ -269,7 +271,7 @@ name: mongodb-configmap
|
||||
data:
|
||||
database_url: mongodb-service
|
||||
```
|
||||
Entonces, dentro de una **deployment config** esta dirección se puede especificar de la siguiente manera para que se cargue dentro del env del pod:
|
||||
Luego, dentro de una **deployment config** esta dirección se puede especificar de la siguiente manera para que se cargue dentro del env del pod:
|
||||
```yaml
|
||||
[...]
|
||||
spec:
|
||||
@@ -290,16 +292,16 @@ name: mongodb-configmap
|
||||
key: database_url
|
||||
[...]
|
||||
```
|
||||
**Ejemplo de config de volume**
|
||||
**Example of volume config**
|
||||
|
||||
Puedes encontrar diferentes ejemplos de archivos yaml de storage configuration en [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
|
||||
**Ten en cuenta que volumes no están dentro de namespaces**
|
||||
Puedes encontrar diferentes ejemplos de archivos yaml de configuración de almacenamiento en [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
|
||||
**Note that volumes aren't inside namespaces**
|
||||
|
||||
### Namespaces
|
||||
|
||||
Kubernetes soporta **múltiples virtual clusters** respaldados por el mismo physical cluster. Estos virtual clusters se llaman **namespaces**. Están pensados para usarse en entornos con muchos users distribuidos entre varios teams o projects. Para clusters con unos pocos hasta decenas de users, no deberías necesitar crear o pensar en namespaces en absoluto. Solo deberías empezar a usar namespaces para tener un mejor control y organización de cada parte de la aplicación desplegada en kubernetes.
|
||||
Kubernetes soporta **multiple virtual clusters** respaldados por el mismo cluster físico. Estos virtual clusters se llaman **namespaces**. Están pensados para usarse en entornos con muchos usuarios repartidos entre varios equipos o proyectos. En clusters con pocos usuarios, hasta decenas, no deberías necesitar crear o pensar en namespaces en absoluto. Solo deberías empezar a usar namespaces para tener un mejor control y organización de cada parte de la application desplegada en kubernetes.
|
||||
|
||||
Namespaces proporcionan un scope para los names. Los names de los resources deben ser únicos dentro de un namespace, pero no entre namespaces. Los namespaces no pueden anidarse unos dentro de otros y **cada** Kubernetes **resource** solo puede estar **en** **un** namespace.
|
||||
Los namespaces proporcionan un scope para los names. Los nombres de los resources deben ser únicos dentro de un namespace, pero no entre namespaces. Los namespaces no pueden anidarse unos dentro de otros y **cada** Kubernetes **resource** solo puede estar **en** **un** **namespace**.
|
||||
|
||||
Hay 4 namespaces por defecto si estás usando minikube:
|
||||
```
|
||||
@@ -313,13 +315,13 @@ kube-system Active 1d
|
||||
- **kube-system**: No está pensado para que lo usen los usuarios y no deberías tocarlo. Es para procesos de master y kubectl.
|
||||
- **kube-public**: Datos accesibles públicamente. Contiene un configmap que contiene información del cluster
|
||||
- **kube-node-lease**: Determina la disponibilidad de un node
|
||||
- **default**: El namespace que el usuario usará para crear recursos
|
||||
- **default**: El namespace que el usuario usará para crear resources
|
||||
```bash
|
||||
#Create namespace
|
||||
kubectl create namespace my-namespace
|
||||
```
|
||||
> [!NOTE]
|
||||
> Ten en cuenta que la mayoría de los recursos de Kubernetes (p. ej. pods, services, replication controllers y otros) están en algunos namespaces. Sin embargo, otros recursos como los recursos de namespace y los recursos de bajo nivel, como nodes y persistenVolumes, no están en un namespace. Para ver qué recursos de Kubernetes están y no están en un namespace:
|
||||
> Ten en cuenta que la mayoría de los recursos de Kubernetes (p. ej., pods, services, replication controllers y otros) están en algunos namespaces. Sin embargo, otros recursos como los namespace resources y los low-level resources, como nodes y persistenVolumes, no están en un namespace. Para ver qué recursos de Kubernetes están y cuáles no están en un namespace:
|
||||
>
|
||||
> ```bash
|
||||
> kubectl api-resources --namespaced=true #In a namespace
|
||||
@@ -332,7 +334,7 @@ kubectl config set-context --current --namespace=<insert-namespace-name-here>
|
||||
```
|
||||
### Helm
|
||||
|
||||
Helm es el **package manager** para Kubernetes. Permite empaquetar archivos YAML y distribuirlos en repositorios públicos y privados. Estos paquetes se llaman **Helm Charts**.
|
||||
Helm es el **gestor de paquetes** para Kubernetes. Permite empaquetar archivos YAML y distribuirlos en repositorios públicos y privados. Estos paquetes se llaman **Helm Charts**.
|
||||
```
|
||||
helm search <keyword>
|
||||
```
|
||||
@@ -340,7 +342,7 @@ Helm is also a template engine that allows to generate config files with variabl
|
||||
|
||||
## Kubernetes secrets
|
||||
|
||||
A **Secret** es un objeto que **contains sensitive data** such as a password, a token or a key. Such information might otherwise be put in a Pod specification or in an image. Users can create Secrets and the system also creates Secrets. The name of a Secret object must be a valid **DNS subdomain name**. Read here [the official documentation](https://kubernetes.io/docs/concepts/configuration/secret/).
|
||||
A **Secret** is an object that **contains sensitive data** such as a password, a token or a key. Such information might otherwise be put in a Pod specification or in an image. Users can create Secrets and the system also creates Secrets. The name of a Secret object must be a valid **DNS subdomain name**. Read here [the official documentation](https://kubernetes.io/docs/concepts/configuration/secret/).
|
||||
|
||||
Secrets might be things like:
|
||||
|
||||
@@ -420,25 +422,25 @@ kubectl get pods #Wait until the pod secretpod is running
|
||||
kubectl exec -it secretpod -- bash
|
||||
env | grep SECRET && cat /etc/foo/my-group/my-username && echo
|
||||
```
|
||||
### Secretos en etcd <a href="#discover-secrets-in-etcd" id="discover-secrets-in-etcd"></a>
|
||||
### Secrets in etcd <a href="#discover-secrets-in-etcd" id="discover-secrets-in-etcd"></a>
|
||||
|
||||
**etcd** es un **almacén clave-valor** consistente y de alta disponibilidad utilizado como respaldo de Kubernetes para todos los datos del clúster. Accedamos a los secretos almacenados en etcd:
|
||||
**etcd** es un **key-value store** consistente y altamente disponible usado como almacenamiento de respaldo de Kubernetes para todos los datos del clúster. Vamos a acceder a los secrets almacenados en etcd:
|
||||
```bash
|
||||
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd
|
||||
```
|
||||
Verás certs, keys y url’s que están ubicadas en el FS. Una vez que las obtengas, podrás conectarte a etcd.
|
||||
Verás que los certs, keys y url’s están ubicados en el FS. Una vez que los obtengas, podrás conectarte a etcd.
|
||||
```bash
|
||||
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health
|
||||
|
||||
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health
|
||||
```
|
||||
Una vez que logres establecer comunicación, podrás obtener los secrets:
|
||||
Una vez que logres establecer la comunicación, podrás obtener los secrets:
|
||||
```bash
|
||||
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>
|
||||
|
||||
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02
|
||||
```
|
||||
**Añadiendo encryption al ETCD**
|
||||
**Añadiendo encryption a ETCD**
|
||||
|
||||
Por defecto todos los secrets se **almacenan en texto plano** dentro de etcd a menos que apliques una capa de encryption. El siguiente ejemplo está basado en [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
|
||||
```yaml:encryption.yaml
|
||||
@@ -454,14 +456,14 @@ keys:
|
||||
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
|
||||
- identity: {}
|
||||
```
|
||||
Después de eso, debes configurar el flag `--encryption-provider-config` en el `kube-apiserver` para que apunte a la ubicación del archivo de configuración creado. Puedes modificar `/etc/kubernetes/manifest/kube-apiserver.yaml` y añadir las siguientes líneas:
|
||||
Después de eso, necesitas establecer la bandera `--encryption-provider-config` en el `kube-apiserver` para que apunte a la ubicación del archivo de configuración creado. Puedes modificar `/etc/kubernetes/manifest/kube-apiserver.yaml` y añadir las siguientes líneas:
|
||||
```yaml
|
||||
containers:
|
||||
- command:
|
||||
- kube-apiserver
|
||||
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>
|
||||
```
|
||||
Desplázate hacia abajo en los volumeMounts:
|
||||
Desplázate hacia abajo en el volumeMounts:
|
||||
```yaml
|
||||
- mountPath: /etc/kubernetes/etcd
|
||||
name: etcd
|
||||
@@ -476,7 +478,7 @@ name: etcd
|
||||
```
|
||||
**Verifying that data is encrypted**
|
||||
|
||||
Los datos se cifran cuando se escriben en etcd. Después de reiniciar tu `kube-apiserver`, cualquier secret recién creado o actualizado debería estar cifrado al almacenarse. Para comprobarlo, puedes usar el programa de línea de comandos `etcdctl` para recuperar el contenido de tu secret.
|
||||
Los datos se cifran cuando se escriben en etcd. Después de reiniciar tu `kube-apiserver`, cualquier secret recién creado o actualizado debe quedar cifrado al almacenarse. Para comprobarlo, puedes usar el programa de línea de comandos `etcdctl` para recuperar el contenido de tu secret.
|
||||
|
||||
1. Crea un nuevo secret llamado `secret1` en el namespace `default`:
|
||||
|
||||
@@ -484,29 +486,29 @@ Los datos se cifran cuando se escriben en etcd. Después de reiniciar tu `kube-a
|
||||
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
|
||||
```
|
||||
|
||||
2. Usando la línea de comandos de etcdctl, lee ese secret desde etcd:
|
||||
2. Usando la línea de comandos `etcdctl`, lee ese secret desde etcd:
|
||||
|
||||
`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`
|
||||
|
||||
where `[...]` must be the additional arguments for connecting to the etcd server.
|
||||
donde `[...]` deben ser los argumentos adicionales para conectarse al servidor etcd.
|
||||
|
||||
3. Verifica que el secret almacenado tenga el prefijo `k8s:enc:aescbc:v1:` que indica que el provider `aescbc` ha cifrado los datos resultantes.
|
||||
4. Verifica que el secret se descifra correctamente cuando se recupera a través de la API:
|
||||
3. Verifica que el secret almacenado tenga el prefijo `k8s:enc:aescbc:v1:` lo que indica que el provider `aescbc` ha cifrado los datos resultantes.
|
||||
4. Verifica que el secret se descifra correctamente al recuperarlo vía la API:
|
||||
|
||||
```
|
||||
kubectl describe secret secret1 -n default
|
||||
```
|
||||
|
||||
should match `mykey: bXlkYXRh`, mydata is encoded, check [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) to completely decode the secret.
|
||||
debe coincidir con `mykey: bXlkYXRh`, mydata está codificado, revisa [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) para decodificar completamente el secret.
|
||||
|
||||
**Since secrets are encrypted on write, performing an update on a secret will encrypt that content:**
|
||||
**Como los secrets se cifran al escribir, realizar una actualización sobre un secret cifrará ese contenido:**
|
||||
```
|
||||
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
|
||||
```
|
||||
**Consejos finales:**
|
||||
|
||||
- Intenta no guardar secretos en el FS, obtenlos de otros lugares.
|
||||
- Echa un vistazo a [https://www.vaultproject.io/](https://www.vaultproject.io) para añadir más protección a tus secretos.
|
||||
- Intenta no guardar secretos en el FS, obténlos de otros lugares.
|
||||
- Consulta [https://www.vaultproject.io/](https://www.vaultproject.io) para añadir más protección a tus secretos.
|
||||
- [https://kubernetes.io/docs/concepts/configuration/secret/#risks](https://kubernetes.io/docs/concepts/configuration/secret/#risks)
|
||||
- [https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm](https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm)
|
||||
|
||||
@@ -520,4 +522,12 @@ https://sickrov.github.io/
|
||||
https://www.youtube.com/watch?v=X48VuDVv0do
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
https://kubernetes.io/docs/concepts/storage/volumes/#image
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
https://kubernetes.io/docs/tasks/configure-pod-container/image-volumes/
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
+45
-39
@@ -6,79 +6,85 @@
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core)
|
||||
|
||||
Al especificar el security context de un Pod puedes usar varios atributos. Desde un punto de vista de defensive security deberías considerar:
|
||||
Al especificar el security context de un Pod puedes usar varios atributos. Desde un punto de vista de seguridad defensiva, deberías considerar:
|
||||
|
||||
- Tener **runASNonRoot** como **True**
|
||||
- Configurar **runAsUser**
|
||||
- Si es posible, considera **limiting** los **permissions** indicando **seLinuxOptions** y **seccompProfile**
|
||||
- **NO** dar acceso a grupo de **privilege** mediante **runAsGroup** y **supplementaryGroups**
|
||||
- Si es posible, considera **limitar** los **permissions** indicando **seLinuxOptions** y **seccompProfile**
|
||||
- **NO** dar acceso a grupos de **privilege** mediante **runAsGroup** y **supplementaryGroups**
|
||||
|
||||
| Parameter | Description |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroup</strong></a><br><em>integer</em></p> | <p>Un grupo suplementario especial que se aplica a <strong>all containers in a pod</strong>. Algunos tipos de volume permiten al Kubelet <strong>change the ownership of that volume</strong> para que pertenezca al pod:<br>1. El GID propietario será el FSGroup<br>2. Se establece el bit setgid (los nuevos archivos creados en el volume pertenecerán a FSGroup)<br>3. Los bits de permission se combinan con rw-rw---- Si no se establece, el Kubelet no modificará la ownership ni los permissions de ningún volume</p> |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroup</strong></a><br><em>integer</em></p> | <p>Un grupo suplementario especial que se aplica a <strong>todos los containers en un pod</strong>. Algunos tipos de volume permiten al Kubelet <strong>cambiar la ownership de ese volume</strong> para que pertenezca al pod:<br>1. El GID propietario será el FSGroup<br>2. Se establece el bit setgid (los nuevos archivos creados en el volume pertenecerán a FSGroup)<br>3. Los permission bits se combinan con rw-rw---- Si no se establece, el Kubelet no modificará la ownership ni los permissions de ningún volume</p> |
|
||||
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroupChangePolicy</strong></a><br><em>string</em></p> | Esto define el comportamiento de **changing ownership and permission of the volume** antes de exponerse dentro del Pod. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | El **GID to run the entrypoint of the container process**. Usa el valor por defecto del runtime si no se establece. También puede configurarse en SecurityContext. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Indica que el container debe ejecutarse como un usuario no root. Si es true, el Kubelet validará la image en tiempo de ejecución para asegurarse de que no se ejecute como UID 0 (root) y fallará al iniciar el container si lo hace. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | El **UID to run the entrypoint of the container process**. Por defecto usa el usuario especificado en los metadatos de la image si no se indica. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | El **SELinux context to be applied to all containers**. Si no se especifica, el runtime del container asignará un SELinux context aleatorio para cada container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a><br><em>More info about</em> <em><strong>Seccomp</strong></em></p> | Las **seccomp options to use by the containers** en este pod. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>supplementalGroups</strong></a><br><em>integer array</em></p> | Una lista de **groups applied to the first process run in each container**, además del GID primario del container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>sysctls</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#sysctl-v1-core"><em>Sysctl</em></a> <em>array</em><br><em>More info about</em> <a href="https://www.garron.me/en/go2linux/sysctl-linux.html"><em><strong>sysctls</strong></em></a></p> | Sysctls contiene una lista de **namespaced sysctls used for the pod**. Los Pods con sysctls no soportados (por el container runtime) podrían fallar al arrancar. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroupChangePolicy</strong></a><br><em>string</em></p> | Esto define el comportamiento de **cambiar la ownership y permission del volume** antes de exponerlo dentro del Pod. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | El **GID para ejecutar el entrypoint del container process**. Usa el default del runtime si no se establece. También puede configurarse en SecurityContext. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Indica que el container debe ejecutarse como un usuario no root. Si es true, el Kubelet validará la image en tiempo de ejecución para asegurarse de que no se ejecuta como UID 0 (root) y fallará al iniciar el container si lo hace. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | El **UID para ejecutar el entrypoint del container process**. Por defecto usa el usuario especificado en los metadata de la image si no se indica. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | El **SELinux context que se aplicará a todos los containers**. Si no se especifica, el container runtime asignará un SELinux context aleatorio para cada container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a><br><em>More info about</em> <em><strong>Seccomp</strong></em></p> | Las **seccomp options que usarán los containers** en este pod. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>supplementalGroups</strong></a><br><em>integer array</em></p> | Una lista de **groups aplicados al primer process que se ejecuta en cada container**, además del GID primario del container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>sysctls</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#sysctl-v1-core"><em>Sysctl</em></a> <em>array</em><br><em>More info about</em> <a href="https://www.garron.me/en/go2linux/sysctl-linux.html"><em><strong>sysctls</strong></em></a></p> | Sysctls contiene una lista de **namespaced sysctls usados para el pod**. Los Pods con sysctls no soportados (por el container runtime) podrían fallar al arrancar. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | Los ajustes específicos de Windows aplicados a todos los containers. Si no se especifica, se usarán las opciones dentro del SecurityContext de un container. |
|
||||
|
||||
## SecurityContext
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core)
|
||||
|
||||
Este context se establece dentro de las **container definitions**. Desde un punto de vista de defensive security deberías considerar:
|
||||
Este context se establece dentro de las **container definitions**. Desde un punto de vista de seguridad defensiva, deberías considerar:
|
||||
|
||||
- **allowPrivilegeEscalation** a **False**
|
||||
- **allowPrivilegeEscalation** en **False**
|
||||
- No añadir **capabilities** sensibles (y eliminar las que no necesites)
|
||||
- **privileged** a **False**
|
||||
- Si es posible, establecer **readOnlyFilesystem** como **True**
|
||||
- Establecer **runAsNonRoot** como **True** y fijar un **runAsUser**
|
||||
- Si es posible, considera **limiting** los **permissions** indicando **seLinuxOptions** y **seccompProfile**
|
||||
- **NO** dar acceso a grupo de **privilege** mediante **runAsGroup.**
|
||||
- **privileged** en **False**
|
||||
- Si es posible, establece **readOnlyFilesystem** como **True**
|
||||
- Establece **runAsNonRoot** como **True** y define un **runAsUser**
|
||||
- Si es posible, considera **limitar** los **permissions** indicando **seLinuxOptions** y **seccompProfile**
|
||||
- **NO** dar acceso a grupos de **privilege** mediante **runAsGroup.**
|
||||
|
||||
Ten en cuenta que, cuando un atributo está definido tanto en **SecurityContext** como en **PodSecurityContext**, el valor especificado en **SecurityContext** tiene **precedence**.
|
||||
Ten en cuenta que, si un atributo está configurado en **ambos SecurityContext y PodSecurityContext**, el valor especificado en **SecurityContext** tiene **precedence**.
|
||||
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>allowPrivilegeEscalation</strong></a><br><em>boolean</em></p> | **AllowPrivilegeEscalation** controla si un process puede **gain more privileges** que su parent process. Este bool controla directamente si el flag no_new_privs se establecerá en el container process. AllowPrivilegeEscalation siempre es true cuando el container se ejecuta como **Privileged** o tiene **CAP_SYS_ADMIN** |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>allowPrivilegeEscalation</strong></a><br><em>boolean</em></p> | **AllowPrivilegeEscalation** controla si un process puede **obtener más privileges** que su proceso padre. Este bool controla directamente si se establecerá el flag no_new_privs en el container process. AllowPrivilegeEscalation siempre es true cuando el container se ejecuta como **Privileged** o tiene **CAP_SYS_ADMIN** |
|
||||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>capabilities</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#capabilities-v1-core"><em>Capabilities</em></a><br><em>More info about</em> <em><strong>Capabilities</strong></em></p> | Las **capabilities to add/drop when running containers**. Por defecto usa el conjunto de capabilities por defecto. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>privileged</strong></a><br><em>boolean</em></p> | Ejecuta el container en modo privileged. Los procesos en containers privileged son, esencialmente, **equivalent to root on the host**. Por defecto es false. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>procMount</strong></a><br><em>string</em></p> | procMount indica el **type of proc mount to use for the containers**. El valor por defecto es DefaultProcMount, que usa los valores por defecto del container runtime para readonly paths y masked paths. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>readOnlyRootFilesystem</strong></a><br><em>boolean</em></p> | Si este **container has a read-only root filesystem**. El valor por defecto es false. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | El **GID to run the entrypoint** del container process. Usa el valor por defecto del runtime si no se establece. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Indica que el container debe **run as a non-root user**. Si es true, el Kubelet validará la image en tiempo de ejecución para asegurarse de que no se ejecute como UID 0 (root) y fallará al iniciar el container si lo hace. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | El **UID to run the entrypoint** del container process. Por defecto usa el usuario especificado en los metadatos de la image si no se indica. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | El **SELinux context to be applied to the container**. Si no se especifica, el runtime del container asignará un SELinux context aleatorio para cada container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a></p> | Las **seccomp options** to use by this container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | Los **Windows specific settings** aplicados a todos los containers. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>capabilities</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#capabilities-v1-core"><em>Capabilities</em></a><br><em>More info about</em> <em><strong>Capabilities</strong></em></p> | Las **capabilities que se añaden/eliminan al ejecutar containers**. Por defecto usa el conjunto de capabilities por defecto. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>privileged</strong></a><br><em>boolean</em></p> | Ejecuta el container en modo privileged. Los procesos en containers privileged son, esencialmente, **equivalentes a root en el host**. Por defecto es false. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>procMount</strong></a><br><em>string</em></p> | procMount indica el **tipo de proc mount que se usará para los containers**. El default es DefaultProcMount, que usa los defaults del container runtime para readonly paths y masked paths. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>readOnlyRootFilesystem</strong></a><br><em>boolean</em></p> | Si este **container tiene un root filesystem de solo lectura**. El default es false. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | El **GID para ejecutar el entrypoint** del container process. Usa el default del runtime si no se establece. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Indica que el container debe **ejecutarse como un usuario no root**. Si es true, el Kubelet validará la image en tiempo de ejecución para asegurarse de que no se ejecuta como UID 0 (root) y fallará al iniciar el container si lo hace. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | El **UID para ejecutar el entrypoint** del container process. Por defecto usa el usuario especificado en los metadata de la image si no se indica. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | El **SELinux context que se aplicará al container**. Si no se especifica, el container runtime asignará un SELinux context aleatorio para cada container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a></p> | Las **seccomp options** que usará este container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | Los **ajustes específicos de Windows** aplicados a todos los containers. |
|
||||
|
||||
## Practical workload review checklist
|
||||
|
||||
Cuando revises un Pod o una plantilla de workload, inspecciona tanto `spec.securityContext` como cada `securityContext` a nivel de container bajo `containers`, `initContainers` y `ephemeralContainers`. Los campos a nivel de container pueden sobrescribir los valores por defecto del pod, así que un default del pod que parezca seguro no garantiza que cada container lo sea.
|
||||
Al revisar un Pod o una plantilla de workload, inspecciona tanto `spec.securityContext` como cada `securityContext` a nivel de container bajo `containers`, `initContainers` y `ephemeralContainers`. Los campos a nivel de container pueden sobrescribir los defaults a nivel de pod, así que un pod que parece seguro por defecto no garantiza que cada container lo sea.
|
||||
|
||||
Combinaciones de alto riesgo a priorizar:
|
||||
|
||||
- `privileged: true`, especialmente con `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports o runtime socket mounts.
|
||||
- `privileged: true`, especialmente con `hostPID`, `hostIPC`, `hostNetwork`, `hostPath`, host ports o montajes del runtime socket.
|
||||
- Capabilities añadidas como `SYS_ADMIN`, `NET_ADMIN`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH` o `DAC_OVERRIDE`.
|
||||
- `allowPrivilegeEscalation: true` o sin definir en containers que puedan ejecutar código controlado por un atacante.
|
||||
- `seccompProfile: Unconfined`, `procMount: Unmasked` o perfiles de runtime ausentes en workloads sensibles.
|
||||
- Root filesystems con escritura habilitada o montajes de volume amplios y escribibles en workloads que procesan entrada no confiable.
|
||||
- Falta de requests y limits de CPU, memory o ephemeral-storage en namespaces multi-tenant.
|
||||
- `allowPrivilegeEscalation: true` o sin definir en containers que pueden ejecutar código controlado por un atacante.
|
||||
- `seccompProfile: Unconfined`, `procMount: Unmasked`, o perfiles del runtime ausentes en workloads sensibles.
|
||||
- Root filesystems escribibles o montajes de volume escribibles amplios en workloads que procesan entrada no confiable.
|
||||
- Requests y limits de CPU, memory o ephemeral-storage ausentes en namespaces multi-tenant.
|
||||
- Faltan presupuestos `spec.resources` a nivel de pod o son irreales, y los principals con `patch` o `update` sobre el subresource `resize` del Pod, porque los clusters compatibles pueden cambiar el estado deseado de CPU y memory en ejecución sin recrear el Pod.
|
||||
|
||||
Para la mayoría de application workloads, una buena base es ejecutar con un UID no root, establecer `runAsNonRoot: true`, establecer `allowPrivilegeEscalation: false`, eliminar todas las capabilities y volver a añadir solo las mínimas necesarias, usar `seccompProfile: RuntimeDefault`, preferir un root filesystem de solo lectura y evitar host namespaces, hostPath mounts y privileged mode.
|
||||
Los resource controls no forman parte de `securityContext`, pero revísalos en el mismo pase del workload porque definen el límite de disponibilidad. Kubernetes moderno puede definir presupuestos de CPU, memory y hugepages a nivel de Pod bajo `spec.resources` además de `resources` a nivel de container. Un Pod con sidecars puede estar limitado por un envelope agregado del Pod incluso cuando un container no tiene limits individuales, mientras que el ephemeral storage local sigue necesitando limits separados de `ephemeral-storage`, `emptyDir.sizeLimit`, LimitRanges y ResourceQuotas. También compara los resources deseados en el Pod spec con `status.containerStatuses[].resources` después de una solicitud de resize en caliente; un resize fallido o pendiente puede dejar el valor solicitado en `spec` mientras kubelet mantiene la asignación previa en runtime e informa una condición `PodResizePending`.
|
||||
|
||||
A nivel de cluster, usa etiquetas de namespace de [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) para aplicar los [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) de Kubernetes donde sea posible. Usa `restricted` para namespaces que lo soporten, al menos `baseline` para namespaces de aplicaciones normales, y mantén las excepciones privileged reducidas, documentadas y aisladas en trusted platform namespaces o node pools.
|
||||
Para la mayoría de los application workloads, una base adecuada es ejecutar con un UID no root, establecer `runAsNonRoot: true`, establecer `allowPrivilegeEscalation: false`, eliminar todas las capabilities y añadir de nuevo solo las mínimas necesarias, usar `seccompProfile: RuntimeDefault`, preferir un root filesystem de solo lectura y evitar host namespaces, montajes hostPath y el modo privileged.
|
||||
|
||||
A nivel de cluster, usa etiquetas de namespace de [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) para aplicar los [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) de Kubernetes cuando sea posible. Usa `restricted` para namespaces que puedan soportarlo, al menos `baseline` para namespaces de aplicaciones normales, y mantén las excepciones privileged reducidas, documentadas y aisladas en namespaces de plataforma de confianza o node pools.
|
||||
|
||||
## References
|
||||
|
||||
- [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core)
|
||||
- [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core)
|
||||
- [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
- [https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)
|
||||
- [https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/](https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/)
|
||||
- [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
|
||||
- [https://kubernetes.io/docs/concepts/security/pod-security-admission/](https://kubernetes.io/docs/concepts/security/pod-security-admission/)
|
||||
- [https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/)
|
||||
- [https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/](https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Reference in New Issue
Block a user