Extensión de Kubernetes
Versiones de Kubernetes upstream revisadas: Kubernetes 1.35, 1.36, 1.37 Última actualización: October 12, 2026
Kubernetes es una plataforma diseñada pensando en la extensibilidad, lo que permite ampliar su funcionalidad de varias maneras. En este capítulo, exploraremos los diversos métodos para extender Kubernetes y cómo aprovechar las características de extensión en Amazon EKS.
Tabla de contenido
- Descripción general de extensiones de Kubernetes
- Recursos personalizados
- Patrón Operator
- Controladores de admisión
- Extensiones de API Server
- Extensiones de Scheduler
- Cloud Controller Manager
- CSI (Container Storage Interface)
- CNI (Container Network Interface)
- Device Plugins
- Características de extensión en Amazon EKS
- Prácticas recomendadas
- Conclusión
Descripción general de extensiones de Kubernetes
Kubernetes proporciona varios puntos de extensión para ampliar y personalizar su funcionalidad base. Los puntos de extensión principales son:
- Recursos personalizados: Definir nuevos tipos de objetos API
- Operators: Combinar recursos personalizados y controladores para administrar aplicaciones complejas
- Controladores de admisión: Interceptar, modificar o validar solicitudes de API
- Extensiones de API Server: Agregar nuevos endpoints a API Server
- Extensiones de Scheduler: Personalizar la lógica de programación de Pods
- Cloud Controller Manager: Integrar características específicas de proveedores de nube
- CSI (Container Storage Interface): Integrar sistemas de almacenamiento
- CNI (Container Network Interface): Integrar soluciones de red
- Device Plugins: Integrar hardware especial
El siguiente diagrama muestra los puntos de extensión principales en Kubernetes:
Elegir un método de extensión
Consideraciones al elegir un método de extensión adecuado:
- Caso de uso: El tipo de funcionalidad que desea extender
- Complejidad: Complejidad de la implementación y el mantenimiento
- Impacto en el rendimiento: Impacto de la extensión en el rendimiento del clúster
- Compatibilidad de actualización: Compatibilidad con las actualizaciones de versión de Kubernetes
- Soporte de la comunidad: Nivel de soporte de la comunidad para el método de extensión
Recursos personalizados
Los recursos personalizados son una manera de extender la API de Kubernetes para definir nuevos tipos de objetos.
El siguiente diagrama muestra cómo funcionan los recursos personalizados:
Definiciones de recursos personalizados (CRD)
CRD es la forma más sencilla de definir nuevos tipos de recursos:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: backups.example.com
spec:
group: example.com
names:
kind: Backup
listKind: BackupList
plural: backups
singular: backup
shortNames:
- bk
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
source:
type: string
destination:
type: string
schedule:
type: string
required:
- source
- destination
status:
type: object
properties:
phase:
type: string
lastBackupTime:
type: string
format: date-time
subresources:
status: {}
additionalPrinterColumns:
- name: Status
type: string
jsonPath: .status.phase
- name: Age
type: date
jsonPath: .metadata.creationTimestampEn el ejemplo anterior, definimos un nuevo tipo de recurso llamado Backup y especificamos el esquema del recurso y columnas de impresión adicionales.
Creación de instancias de recursos personalizados
Después de que la condición Established de CRD sea verdadera, cree una instancia. Un CRD almacena y valida datos; no ejecuta copias de seguridad sin un controlador.
apiVersion: example.com/v1
kind: Backup
metadata:
name: daily-backup
spec:
source: /data
destination: s3://my-bucket/backups
schedule: "0 0 * * *"Validación de recursos personalizados
Puede validar recursos personalizados mediante esquemas OpenAPI v3 en CRD:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
minimum: 1
maximum: 10
image:
type: string
minLength: 1
required:
- replicas
- imageEn el ejemplo anterior, el campo replicas debe ser un entero entre 1 y 10, y el campo image no debe estar vacío; las comprobaciones de disponibilidad y firma de imágenes requieren una política independiente.
Gestión de versiones
Los CRD admiten múltiples versiones para permitir la evolución de la API:
versions:
- name: v1alpha1
served: true
storage: false
- name: v1beta1
served: true
storage: false
- name: v1
served: true
storage: trueEn el ejemplo anterior, se sirven tres versiones, v1alpha1, v1beta1 y v1, pero las nuevas escrituras usan v1. Este es un fragmento de versiones: incluya un esquema estructural para cada versión. Los objetos existentes no se reescriben automáticamente; migre el almacenamiento antes de eliminar una entrada antigua de storedVersions.
Webhooks de conversión
Puede usar webhooks de conversión para manejar conversiones entre diferentes versiones:
# Merge this spec fragment into the complete CRD above.
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: default
name: example-conversion-webhook
path: /convert
caBundle: <base64-encoded-ca-cert>
conversionReviewVersions:
- v1Patrón Operator
El patrón Operator es una manera de automatizar el conocimiento operativo de aplicaciones complejas mediante la combinación de recursos personalizados y controladores.
El siguiente diagrama muestra cómo funciona el patrón Operator:
Conceptos de Operator
Un Operator consta de los siguientes componentes:
- Custom Resource Definition (CRD): Define el esquema de los recursos que se administrarán
- Controller: Lógica que supervisa los recursos personalizados y los reconcilia con el estado deseado
- Cliente de API de Kubernetes: Cliente para interactuar con la API de Kubernetes
Ejemplo de Operator
Ejemplo de Operator de base de datos:
# Custom Resource Definition
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: databases.example.com
spec:
group: example.com
names:
kind: Database
listKind: DatabaseList
plural: databases
singular: database
shortNames:
- db
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
engine:
type: string
enum:
- mysql
- postgresql
version:
type: string
storageSize:
type: string
replicas:
type: integer
minimum: 1
required:
- engine
- version
- storageSize
status:
type: object
properties:
phase:
type: string
endpoint:
type: string
subresources:
status: {}# Database Instance
apiVersion: example.com/v1
kind: Database
metadata:
name: my-db
spec:
engine: postgresql
version: "17"
storageSize: 10Gi
replicas: 3Herramientas de desarrollo de Operators
Herramientas para desarrollar Operators:
- Operator SDK: Desarrollar Operators mediante Go, Ansible o Helm
- KUDO (Kubernetes Universal Declarative Operator): Desarrollar Operators de forma declarativa
- Kubebuilder: Marco de desarrollo de Operators basado en Go
- Metacontroller: Desarrollo de Operators basado en webhooks
Ejemplo de Operator SDK
Creación de un Operator mediante Operator SDK:
: "${OPERATOR_IMAGE:?Set a registry image tag or digest you control}"
# Install a reviewed supported Operator SDK release and verify its checksum first.
# Create new operator project
operator-sdk init --domain example.com --repo github.com/example/database-operator
# Create API
operator-sdk create api --group database --version v1 --kind Database --resource --controller
# Implement controller (main.go, controllers/database_controller.go, etc.)
# Build and deploy operator
make docker-build docker-push IMG="$OPERATOR_IMAGE"
make deploy IMG="$OPERATOR_IMAGE"Operators populares
Operators populares de código abierto:
- Prometheus Operator: Administra la pila de monitorización de Prometheus
- Elasticsearch Operator: Administra clústeres de Elasticsearch
- CoreOS etcd Operator (archivado): Ejemplo histórico de automatización de etcd; no es una recomendación de instalación actual.
- PostgreSQL Operator: Administra bases de datos PostgreSQL
- OpenTelemetry Operator: Implementa Jaeger v2; el anterior Jaeger Operator solo admite el Jaeger v1 retirado.
- Strimzi Kafka Operator: Administra clústeres de Apache Kafka
- Istio in-cluster Operator (eliminado en 1.24): Ejemplo histórico; use flujos de instalación compatibles de Helm/istioctl.
Controladores de admisión
Los controladores de admisión son plugins que interceptan solicitudes al API Server de Kubernetes y las modifican o validan.
El siguiente diagrama muestra cómo funcionan los controladores de admisión:
Tipos de controladores de admisión
Kubernetes tiene dos tipos de controladores de admisión:
- Controladores de admisión mutantes: Pueden modificar recursos
- Controladores de admisión de validación: Solo pueden validar recursos
Controladores de admisión integrados
Kubernetes tiene varios controladores de admisión integrados:
- NamespaceLifecycle: Evita la creación de recursos en namespaces que se están eliminando
- LimitRanger: Establece límites de recursos predeterminados para Pods y contenedores
- ServiceAccount: Establece o valida de forma predeterminada la ServiceAccount del Pod e inyecta un volumen de token proyectado, salvo que se desactive el montaje automático; otros controladores crean cuentas predeterminadas.
- DefaultStorageClass: Asigna una clase de almacenamiento predeterminada a los PVC
- ResourceQuota: Limita el uso de recursos por namespace
- PodSecurity: Impone los Pod Security Standards del namespace; PodSecurityPolicy se eliminó en 1.25.
- NodeRestriction: Limita los recursos que los nodos pueden modificar
Controladores de admisión de webhooks
Puede utilizar controladores de admisión de webhooks para implementar lógica personalizada:
# Mutating Webhook Configuration
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: pod-mutating-webhook
webhooks:
- name: pod-mutator.example.com
clientConfig:
service:
namespace: default
name: pod-mutating-webhook
path: "/mutate"
caBundle: <base64-encoded-ca-cert>
rules:
- apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
operations: ["CREATE"]
scope: "Namespaced"
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5# Validating Webhook Configuration
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: pod-validating-webhook
webhooks:
- name: pod-validator.example.com
clientConfig:
service:
namespace: default
name: pod-validating-webhook
path: "/validate"
caBundle: <base64-encoded-ca-cert>
rules:
- apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
operations: ["CREATE", "UPDATE"]
scope: "Namespaced"
admissionReviewVersions: ["v1"]
sideEffects: None
timeoutSeconds: 5Implementación del servidor de webhooks
Estos fragmentos de Go pertenecen a un solo archivo e implementan manejadores AdmissionReview v1. Conecte /mutate y /validate a HTTPS con un certificado que coincida con el Service y un paquete de CA. No realizan efectos secundarios externos y son seguros para dry-run; limite la configuración de webhook a los namespaces previstos. La comprobación de tags es un ejemplo de política, no una validación completa de referencia o firma de imágenes.
package main
import (
"encoding/json"
"net/http"
"strings"
admissionv1 "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func readPodReview(w http.ResponseWriter, r *http.Request) (*admissionv1.AdmissionRequest, *corev1.Pod, bool) {
if r.Method != http.MethodPost || r.Body == nil {
http.Error(w, "POST body required", http.StatusBadRequest)
return nil, nil, false
}
var review admissionv1.AdmissionReview
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 2<<20)).Decode(&review); err != nil {
http.Error(w, "Invalid AdmissionReview JSON", http.StatusBadRequest)
return nil, nil, false
}
req := review.Request
if review.APIVersion != "admission.k8s.io/v1" || review.Kind != "AdmissionReview" || req == nil || req.UID == "" {
http.Error(w, "AdmissionReview v1 request and UID required", http.StatusBadRequest)
return nil, nil, false
}
if req.Kind.Group != "" || req.Kind.Version != "v1" || req.Kind.Kind != "Pod" ||
(req.Operation != admissionv1.Create && req.Operation != admissionv1.Update) {
http.Error(w, "Only Pod CREATE/UPDATE is supported", http.StatusBadRequest)
return nil, nil, false
}
var pod corev1.Pod
if err := json.Unmarshal(req.Object.Raw, &pod); err != nil {
http.Error(w, "Invalid Pod JSON", http.StatusBadRequest)
return nil, nil, false
}
return req, &pod, true
}
func writeReview(w http.ResponseWriter, response admissionv1.AdmissionResponse) {
review := admissionv1.AdmissionReview{
TypeMeta: metav1.TypeMeta{APIVersion: "admission.k8s.io/v1", Kind: "AdmissionReview"},
Response: &response,
}
data, err := json.Marshal(review)
if err != nil {
http.Error(w, "Response encoding failed", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(data)
}
func writePatch(w http.ResponseWriter, req *admissionv1.AdmissionRequest, patches []map[string]interface{}) {
response := admissionv1.AdmissionResponse{UID: req.UID, Allowed: true}
if len(patches) > 0 {
data, err := json.Marshal(patches)
if err != nil {
http.Error(w, "Patch encoding failed", http.StatusInternalServerError)
return
}
patchType := admissionv1.PatchTypeJSONPatch
response.PatchType, response.Patch = &patchType, data
}
writeReview(w, response)
}
func deny(w http.ResponseWriter, req *admissionv1.AdmissionRequest, message string) {
writeReview(w, admissionv1.AdmissionResponse{
UID: req.UID, Allowed: false,
Result: &metav1.Status{Status: "Failure", Reason: metav1.StatusReasonForbidden, Code: 403, Message: message},
})
}
func mutateHandler(w http.ResponseWriter, r *http.Request) {
req, pod, ok := readPodReview(w, r)
if !ok { return }
if pod.Labels["injected-by"] == "mutating-webhook" {
writePatch(w, req, nil)
return
}
if pod.Labels == nil { pod.Labels = map[string]string{} }
pod.Labels["injected-by"] = "mutating-webhook"
// Add the whole map, preserving existing labels. Works when labels was absent.
writePatch(w, req, []map[string]interface{}{{"op": "add", "path": "/metadata/labels", "value": pod.Labels}})
}func validateHandler(w http.ResponseWriter, r *http.Request) {
req, pod, ok := readPodReview(w, r)
if !ok { return }
images := []string{}
for _, c := range pod.Spec.Containers { images = append(images, c.Image) }
for _, c := range pod.Spec.InitContainers { images = append(images, c.Image) }
for _, c := range pod.Spec.EphemeralContainers { images = append(images, c.Image) }
for _, image := range images {
if strings.Contains(image, "@") { continue } // Digest references have no implicit latest tag.
last := image[strings.LastIndex(image, "/")+1:]
if !strings.Contains(last, ":") || strings.HasSuffix(last, ":latest") {
deny(w, req, "Use an explicit non-latest tag or digest for every container")
return
}
}
writeReview(w, admissionv1.AdmissionResponse{UID: req.UID, Allowed: true})
}Proyectos populares de controladores de admisión
- OPA Gatekeeper: Aplicación de políticas mediante Open Policy Agent
- Kyverno: Motor de políticas basado en YAML
- Istio: Inyección de sidecar de Service mesh
- cert-manager: Gestión de certificados TLS
Extensiones de API Server
Las extensiones de API Server son una manera de agregar nuevos endpoints al API Server de Kubernetes.
API Servers de extensión
Los API Servers de extensión son servidores que se ejecutan por separado del API Server de Kubernetes y proporcionan API personalizadas:
# APIService Definition
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1.example.com
spec:
group: example.com
version: v1
groupPriorityMinimum: 1000
versionPriority: 15
service:
name: example-api
namespace: default
caBundle: <base64-encoded-ca-cert>Implementación de API Server de extensión
Un API Server de extensión consta de los siguientes componentes:
- API Server: Proporciona una interfaz similar al API Server de Kubernetes
- Manejadores de recursos: Gestionan solicitudes para tipos de recursos específicos
- Backend de almacenamiento: Almacena datos de recursos
Este es un esquema de implementación, no un programa independiente. Comience con la versión oficial de sample-apiserver que coincida con sus dependencias k8s.io; configure el servicio seguro, la autenticación/autorización delegada, los tipos reales example.com/v1, el almacenamiento y el contexto de apagado. El grupo/versión de APIService debe coincidir con el servidor.
// Extension API Server Example
func main() {
// Server configuration
config := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
config.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
sampleopenapi.GetOpenAPIDefinitions,
openapi.NewDefinitionNamer(apiserver.Scheme),
)
config.EnableIndex = true
config.EnableDiscovery = true
// Create server
server, err := config.Complete().New("sample-apiserver", genericapiserver.NewEmptyDelegate())
if err != nil {
log.Fatalf("Error creating server: %v", err)
}
// Set API group info
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(
samplev1.GroupName,
apiserver.Scheme,
metav1.ParameterCodec,
apiserver.Codecs,
)
// Set storage
apiGroupInfo.VersionedResourcesStorageMap["v1"] = map[string]rest.Storage{
"widgets": NewWidgetStorage(),
}
// Install API group
if err := server.InstallAPIGroup(&apiGroupInfo); err != nil {
log.Fatalf("Error installing API group: %v", err)
}
// Run server
if err := server.PrepareRun().Run(stopCh); err != nil {
log.Fatalf("Error running server: %v", err)
}
}Capa de agregación
La capa de agregación hace que múltiples API Servers aparezcan como un único API Server:
+-----------------+
| |
| kube-apiserver |
| |
+-------+---------+
|
v
+--------------------+--------------------+
| |
| |
+-----------v-----------+ +------------v------------+
| | | |
| metrics-server | | example-apiserver |
| | | |
+-----------------------+ +-------------------------+Extensiones de Scheduler
Las extensiones de Scheduler son una manera de personalizar el comportamiento del Scheduler de Kubernetes.
Framework de Scheduler
El framework de Scheduler introducido en Kubernetes 1.15 permite extender varias etapas del pipeline de programación mediante plugins:
- Queue Sort: Ordenar Pods en la cola de programación
- Pre-filter: Comprobar el estado del Pod y del clúster antes del filtrado
- Filter: Filtrar los nodos que no pueden ejecutar el Pod
- Post-filter: Realizar acciones después del filtrado
- Pre-score: Realizar acciones antes del cálculo de la puntuación
- Score: Asignar puntuaciones a los nodos
- Normalize Score: Normalizar puntuaciones
- Reserve: Reservar recursos para el Pod
- Permit: Permitir, denegar o retrasar la programación del Pod
- Pre-bind: Realizar acciones antes de la vinculación
- Bind: Vincular el Pod a un nodo
- Post-bind: Realizar acciones después de la vinculación
Configuración de Scheduler
Ejemplo de configuración de Scheduler:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
leaderElection:
leaderElect: true
profiles:
- schedulerName: custom-scheduler
pluginConfig:
- name: NodeResourcesFit
args:
scoringStrategy:
type: MostAllocated
resources:
- name: cpu
weight: 1
- name: memory
weight: 1Scheduler personalizado
El siguiente Deployment requiere una imagen custom-scheduler compilada, un ConfigMap denominado custom-scheduler-config que contenga el config.yaml anterior y una ServiceAccount con RBAC de programación/Lease revisado. Use autenticación dentro del clúster; un worker no puede montar el scheduler.conf de un plano de control administrado. El schedulerName debe coincidir con el Pod.
apiVersion: apps/v1
kind: Deployment
metadata:
name: custom-scheduler
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: custom-scheduler
template:
metadata:
labels:
app: custom-scheduler
spec:
serviceAccountName: custom-scheduler
nodeSelector:
kubernetes.io/os: linux
containers:
- name: custom-scheduler
image: example/custom-scheduler:REPLACE_WITH_TESTED_RELEASE
command: [/custom-scheduler, --config=/etc/scheduler/config.yaml]
volumeMounts:
- name: config
mountPath: /etc/scheduler
readOnly: true
volumes:
- name: config
configMap:
name: custom-scheduler-configEspecificación de un Scheduler personalizado para un Pod:
apiVersion: v1
kind: Pod
metadata:
name: custom-scheduled-pod
spec:
schedulerName: custom-scheduler
containers:
- name: container
image: nginx:1.30.4Cloud Controller Manager
Cloud Controller Manager proporciona una interfaz entre Kubernetes y los proveedores de nube.
Componentes de Cloud Controller Manager
Cloud Controller Manager consta de los siguientes controladores:
- Node Controller: Actualiza la información de los nodos mediante API de proveedores de nube
- Route Controller: Configura rutas en redes de nube
- Service Controller: Crea, actualiza y elimina balanceadores de carga de nube
AWS Cloud Controller Manager
El AWS CCM externo es para Kubernetes autogestionado en AWS. Elija una versión de cloud-provider-aws compatible con Kubernetes y siga su procedimiento de clúster existente para los requisitos previos de ServiceAccount/RBAC, IAM, etiquetas de clúster, nombres de nodos y migración de --cloud-provider=external. Su repositorio de imágenes es registry.k8s.io/provider-aws/cloud-controller-manager. Las entradas arbitrarias de cloud.conf no pueden sustituir el etiquetado de VPC/subnet.
No puede instalar este DaemonSet en el plano de control de EKS administrado por AWS ni montar su scheduler.conf. En EKS, use la integración de nube administrada por el servicio y las capacidades compatibles de AWS Load Balancer Controller o Auto Mode, con un propietario de controlador por recurso.
CSI (Container Storage Interface)
CSI proporciona una interfaz estándar entre Kubernetes y los sistemas de almacenamiento.
El siguiente diagrama muestra la arquitectura y el funcionamiento de CSI:
Arquitectura de CSI
CSI consta de los siguientes componentes:
- CSI Controller Plugin: Gestiona la creación, eliminación, snapshots de volúmenes, etc.
- CSI Node Plugin: Gestiona el montaje, desmontaje de volúmenes, etc.
- CSI Driver: Implementación que se integra con sistemas de almacenamiento específicos
+-------------------+
| |
| Kubernetes |
| (External |
| Provisioner) |
| |
+--------+----------+
|
| gRPC
v
+--------+----------+
| |
| CSI Driver |
| |
+--------+----------+
|
| Storage Protocol
v
+--------+----------+
| |
| Storage System |
| |
+-------------------+Implementación de CSI Driver
Lo siguiente es una plantilla para autores de drivers, no una instalación completa. Proporcione la imagen y los argumentos del driver, versiones de sidecar compatibles, ServiceAccounts/RBAC y el registro de CSIDriver del proveedor. NodePlugin se ejecuta en Linux y requiere las rutas de host y privilegios documentados.
# CSI Controller Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: csi-controller
spec:
replicas: 1
selector:
matchLabels:
app: csi-controller
template:
metadata:
labels:
app: csi-controller
spec:
serviceAccountName: csi-controller
nodeSelector:
kubernetes.io/os: linux
containers:
- name: csi-provisioner
image: registry.k8s.io/sig-storage/csi-provisioner:REPLACE_WITH_COMPATIBLE_RELEASE
args:
- "--csi-address=$(ADDRESS)"
- "--v=5"
env:
- name: ADDRESS
value: /var/lib/csi/sockets/pluginproxy/csi.sock
volumeMounts:
- name: socket-dir
mountPath: /var/lib/csi/sockets/pluginproxy/
- name: csi-attacher
image: registry.k8s.io/sig-storage/csi-attacher:REPLACE_WITH_COMPATIBLE_RELEASE
args:
- "--csi-address=$(ADDRESS)"
- "--v=5"
env:
- name: ADDRESS
value: /var/lib/csi/sockets/pluginproxy/csi.sock
volumeMounts:
- name: socket-dir
mountPath: /var/lib/csi/sockets/pluginproxy/
- name: csi-driver
image: example/csi-driver:v1.0.0
args:
- "--endpoint=$(CSI_ENDPOINT)"
- "--nodeid=$(NODE_ID)"
env:
- name: CSI_ENDPOINT
value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock
- name: NODE_ID
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: socket-dir
mountPath: /var/lib/csi/sockets/pluginproxy/
volumes:
- name: socket-dir
emptyDir: {}
---
# CSI Node Service
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: csi-node
spec:
selector:
matchLabels:
app: csi-node
template:
metadata:
labels:
app: csi-node
spec:
serviceAccountName: csi-node
nodeSelector:
kubernetes.io/os: linux
hostNetwork: true
containers:
- name: csi-node-driver-registrar
image: registry.k8s.io/sig-storage/csi-node-driver-registrar:REPLACE_WITH_COMPATIBLE_RELEASE
args:
- "--csi-address=$(ADDRESS)"
- "--kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)"
- "--v=5"
env:
- name: ADDRESS
value: /csi/csi.sock
- name: DRIVER_REG_SOCK_PATH
value: /var/lib/kubelet/plugins/example.csi.k8s.io/csi.sock
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: registration-dir
mountPath: /registration
- name: csi-driver
image: example/csi-driver:v1.0.0
args:
- "--endpoint=$(CSI_ENDPOINT)"
- "--nodeid=$(NODE_ID)"
env:
- name: CSI_ENDPOINT
value: unix:///csi/csi.sock
- name: NODE_ID
valueFrom:
fieldRef:
fieldPath: spec.nodeName
securityContext:
privileged: true
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: pods-mount-dir
mountPath: /var/lib/kubelet/pods
mountPropagation: "Bidirectional"
volumes:
- name: plugin-dir
hostPath:
path: /var/lib/kubelet/plugins/example.csi.k8s.io
type: DirectoryOrCreate
- name: registration-dir
hostPath:
path: /var/lib/kubelet/plugins_registry
type: Directory
- name: pods-mount-dir
hostPath:
path: /var/lib/kubelet/pods
type: DirectoryClase de almacenamiento y PVC
Ejemplo de clase de almacenamiento y PVC mediante CSI Driver:
# Storage Class
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-csi
provisioner: example.csi.k8s.io
parameters:
type: ssd
csi.storage.k8s.io/fstype: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: WaitForFirstConsumer
---
# PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: example-csiCSI Drivers populares
- AWS EBS CSI Driver: Gestión de volúmenes AWS EBS
- AWS EFS CSI Driver: Gestión de sistemas de archivos AWS EFS
- GCE PD CSI Driver: Gestión de discos persistentes de Google Compute Engine
- Azure Disk CSI Driver: Gestión de discos de Azure
- Ceph RBD CSI Driver: Gestión de volúmenes Ceph RBD
- NFS CSI Driver: Gestión de volúmenes NFS
CNI (Container Network Interface)
CNI proporciona una interfaz estándar entre Kubernetes y las soluciones de red.
El siguiente diagrama muestra la arquitectura y el funcionamiento de CNI:
Arquitectura de CNI
CNI consta de los siguientes componentes:
- CNI Plugin: Configura las interfaces de red de contenedores
- IPAM Plugin: Asignación y gestión de direcciones IP
- Meta Plugin: Combina varios plugins
+-------------------+
| |
| Kubernetes |
| CRI runtime |
| (via kubelet) |
+--------+----------+
|
| CNI Spec
v
+--------+----------+
| |
| CNI Plugin |
| |
+--------+----------+
|
| Network Configuration
v
+--------+----------+
| |
| Network |
| |
+-------------------+Configuración de CNI Plugin
Este ejemplo de bridge/host-local para un solo nodo ilustra el contrato de CNI; un clúster necesita subredes únicas por nodo y enrutamiento entre nodos. CNI es llamado por el runtime CRI, no directamente por kubelet moderno.
{
"cniVersion": "0.4.0",
"name": "example-network",
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24",
"routes": [
{ "dst": "0.0.0.0/0" }
]
}
}CNI Plugins populares
- Calico: CNI con políticas de red y características de seguridad mejoradas
- Flannel: Proporciona redes superpuestas sencillas
- Cilium: Solución de red y seguridad basada en eBPF
- Weave Net (archivado): Proyecto histórico de redes multi-host; evalúe alternativas mantenidas.
- AWS VPC CNI: CNI integrado con AWS VPC
- Azure CNI: CNI integrado con redes virtuales de Azure
- Antrea: Solución de red basada en Open vSwitch
Instalación de CNI Plugin
Ejemplo de instalación del plugin CNI Calico:
# Use the official Calico installation guide for your distribution.
# Select a supported release and inspect the operator/custom-resources manifests.
# Do not install a second primary CNI over an existing cluster network.
kubectl get nodes -o wide
kubectl -n kube-system get daemonsetsDevice Plugins
Los Device Plugins proporcionan una interfaz entre Kubernetes y hardware especial.
Arquitectura de Device Plugin
Los Device Plugins constan de los siguientes componentes:
- Servidor de Device Plugin: Gestiona el descubrimiento, la asignación, la inicialización de dispositivos, etc.
- kubelet: Se comunica con los Device Plugins para asignar dispositivos a Pods
+-------------------+
| |
| Kubernetes |
| (kubelet) |
| |
+--------+----------+
|
| Device Plugin API
v
+--------+----------+
| |
| Device Plugin |
| |
+--------+----------+
|
| Device Management
v
+--------+----------+
| |
| Hardware Device |
| |
+-------------------+NVIDIA GPU Device Plugin
Ejemplo de implementación de NVIDIA GPU Device Plugin:
Primero configure drivers de NVIDIA compatibles, Container Toolkit y el runtime de contenedores. Fije una versión probada del Helm chart oficial de device-plugin de NVIDIA y seleccione nodos GPU Linux. Evite una instalación duplicada cuando GPU Operator o Auto Mode ya sea propietario del plugin.
Pod de solicitud de GPU
Ejemplo de Pod que solicita GPU:
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
restartPolicy: Never
nodeSelector:
kubernetes.io/os: linux
containers:
- name: cuda-container
image: nvidia/cuda:REPLACE_WITH_DRIVER_COMPATIBLE_TAG
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1Device Plugins populares
- NVIDIA GPU Device Plugin: Gestión de GPU NVIDIA
- AMD GPU Device Plugin: Gestión de GPU AMD
- FPGA Device Plugin: Gestión de dispositivos FPGA
- InfiniBand Device Plugin: Gestión de dispositivos InfiniBand
- SR-IOV Network Device Plugin: Gestión de dispositivos de red SR-IOV
Características de extensión en Amazon EKS
El soporte de versiones de EKS difiere del upstream. A fecha de 2026-10-12, el soporte estándar de EKS cubre 1.34–1.37; compruebe también cada matriz de compatibilidad de add-on/controlador.
Amazon EKS admite varias características de extensión para ampliar la funcionalidad de los clústeres de Kubernetes.
El siguiente diagrama muestra la arquitectura de características de extensión en Amazon EKS:
Add-ons de EKS
Amazon EKS proporciona los siguientes add-ons:
- Amazon VPC CNI: Redes integradas con AWS VPC
- CoreDNS: Servicio DNS dentro del clúster
- kube-proxy: Proxy de red
- Amazon EBS CSI Driver: Gestión de volúmenes EBS
- AWS Load Balancer Controller: Se instala por separado con Helm/manifests compatibles; no suponga que cada extensión sea un add-on administrado de EKS.
set -euo pipefail
: "${CLUSTER_NAME:?Set cluster name}"
KUBERNETES_VERSION=$(aws eks describe-cluster --name "$CLUSTER_NAME" --query cluster.version --output text)
aws eks list-addons --cluster-name "$CLUSTER_NAME"
aws eks describe-addon-versions --addon-name amazon-ebs-csi-driver --kubernetes-version "$KUBERNETES_VERSION"
# Choose a compatible version and prepare the controller's scoped IAM role first.
: "${ADDON_VERSION:?Set reviewed compatible add-on version}"
: "${EBS_ROLE_ARN:?Set EBS CSI IRSA role ARN}"
aws eks create-addon --cluster-name "$CLUSTER_NAME" --addon-name amazon-ebs-csi-driver \
--addon-version "$ADDON_VERSION" --service-account-role-arn "$EBS_ROLE_ARN"
# For an existing installation, use update-addon instead of create-addon.
# To stop EKS management while retaining the workload (not uninstall it):
# aws eks delete-addon --cluster-name "$CLUSTER_NAME" --addon-name amazon-ebs-csi-driver --preserveAWS Controllers for Kubernetes (ACK)
ACK es una colección de Operators que permite administrar recursos de AWS desde Kubernetes:
set -euo pipefail
: "${ACK_VERSION:?Set a reviewed S3 controller chart version}"
: "${AWS_REGION:?Set target service region}"
# First prepare ack-s3-controller ServiceAccount with scoped IRSA/Pod Identity permissions.
helm upgrade --install ack-s3-controller oci://public.ecr.aws/aws-controllers-k8s/s3-chart \
--version "$ACK_VERSION" --namespace ack-system --create-namespace \
--set aws.region="$AWS_REGION" --set serviceAccount.create=false \
--set serviceAccount.name=ack-s3-controller
# Creating a Bucket CR provisions a real AWS resource: review IAM, naming and retention first.El siguiente ejemplo de Bucket aprovisiona un recurso de AWS real cuando se configuran el controlador y los permisos de IAM. Sustituya el nombre por un valor globalmente único y revise la configuración de ciclo de vida/retención. Eliminar el objeto de Kubernetes puede eliminar el bucket; configure la política de eliminación del controlador según sus requisitos de retención de datos.
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
name: example-bucket
spec:
name: replace-with-your-globally-unique-bucket-nameAWS Load Balancer Controller
AWS Load Balancer Controller integra los Services e Ingresses de Kubernetes con balanceadores de carga de AWS:
# ALB Ingress example
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80IAM Roles for Service Accounts (IRSA)
IRSA permite que los Pods accedan de forma segura a servicios de AWS asociando roles de AWS IAM con ServiceAccounts de Kubernetes:
# Create OIDC provider
: "${S3_READ_POLICY_ARN:?Set a customer-managed policy restricted to your bucket/prefix}"
eksctl utils associate-iam-oidc-provider \
--cluster my-cluster \
--approve
# Create IAM role and service account
eksctl create iamserviceaccount \
--cluster my-cluster \
--namespace default \
--name my-service-account \
--attach-policy-arn "$S3_READ_POLICY_ARN" \
--approve
# Pod using service account
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: s3-reader
spec:
serviceAccountName: my-service-account
restartPolicy: Never
containers:
- name: aws-cli
image: public.ecr.aws/aws-cli/aws-cli:REPLACE_WITH_TESTED_RELEASE
command: [aws]
args: [sts, get-caller-identity]
EOFPrácticas recomendadas
Exploremos las prácticas recomendadas que se deben considerar al implementar características de extensión de Kubernetes.
Prácticas recomendadas de diseño
- Usar interfaces estándar: Use interfaces estándar como CSI y CNI cuando sea posible
- Diseño de API declarativa: Diseñe API declarativas en lugar de imperativas
- Seguir los principios de diseño de Kubernetes: Siga principios como el patrón Controller y level-triggering
- Gestión de versiones: Gestione las versiones de API y mantenga la compatibilidad
- Principio de mínimo privilegio: Otorgue solo los permisos mínimos necesarios
Prácticas recomendadas de implementación
- Aprovechar bibliotecas reutilizables: Aproveche bibliotecas como client-go y controller-runtime
- Manejo adecuado de errores: Maneje y registre adecuadamente las situaciones de error
- Backoff exponencial: Use backoff exponencial para los reintentos
- Establecer límites de recursos: Establezca límites de memoria y CPU
- Informes de estado: Informe con precisión el estado de los recursos
Prácticas recomendadas de despliegue
- Despliegue gradual: Realice el despliegue gradualmente en lugar de cambiar todo de una vez
- Gestión de versiones: Evite usar el tag latest para las imágenes
- Health checks: Configure probes de liveness y readiness adecuadas
- Registro y monitorización: Configure un registro y una monitorización integrales
- Documentación: Documente las API y su uso
Prácticas recomendadas de seguridad
- Principio de mínimo privilegio: Otorgue solo los permisos mínimos necesarios
- Usar RBAC: Configure políticas RBAC adecuadas
- Network Policies: Configure políticas de red adecuadas
- Escaneo de imágenes: Analice las imágenes de contenedores en busca de vulnerabilidades
- Gestión de secretos: Administre los secretos de forma segura
Prácticas recomendadas específicas de EKS
- Usar add-ons administrados: Use add-ons administrados por EKS cuando sea posible
- Usar IRSA: Use IRSA para la gestión de permisos IAM por Pod
- Configuración de VPC CNI: Configure VPC CNI según los requisitos de red
- Security Groups: Configure Security Groups adecuados
- Optimización de costes: Seleccione tipos y tamaños de instancia adecuados
Conclusión
Kubernetes proporciona varios puntos de extensión para ampliar y personalizar su funcionalidad base. Los recursos personalizados, Operators, controladores de admisión, extensiones de API Server, extensiones de Scheduler, CSI, CNI y Device Plugins permiten adaptar Kubernetes a diversos entornos y requisitos.
Amazon EKS admite estas características de extensión y, además, proporciona características específicas de AWS como add-ons de EKS, ACK, AWS Load Balancer Controller e IRSA para simplificar la integración entre Kubernetes y los servicios de AWS.
Al implementar características de extensión de Kubernetes, es importante seguir prácticas recomendadas como el uso de interfaces estándar, el diseño de API declarativa y el principio de mínimo privilegio. Esto permite crear entornos de Kubernetes estables y escalables.
Cuestionario
Para comprobar lo que aprendió en este capítulo, pruebe el Cuestionario de extensión de Kubernetes.
Referencias de verificación
- https://kubernetes.io/releases/
- https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
- https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/
- https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
- https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/
- https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/
- https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/
- https://github.com/kubernetes/kubernetes/blob/v1.37.0/pkg/scheduler/apis/config/types.go
- https://github.com/kubernetes/cloud-provider-aws/blob/master/docs/prerequisites.md
- https://github.com/kubernetes/cloud-provider-aws/blob/master/examples/existing-cluster/base/aws-cloud-controller-manager-daemonset.yaml
- https://github.com/kubernetes-sigs/kubebuilder/blob/master/README.md
- https://github.com/operator-framework/operator-sdk/blob/master/README.md
- https://github.com/NVIDIA/k8s-device-plugin/blob/main/README.md
- https://github.com/jaegertracing/jaeger-operator/blob/main/README.md
- https://istio.io/latest/blog/2024/in-cluster-operator-deprecation-announcement/
- https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html
- https://docs.aws.amazon.com/eks/latest/userguide/lbc-helm.html
- https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions-standard.html
- https://github.com/aws-controllers-k8s/community/blob/main/docs/content/docs/user-docs/install.md
- https://github.com/aws-controllers-k8s/s3-controller/blob/main/helm/values.yaml






