Extending Kubernetes
Versiones compatibles: Kubernetes 1.32, 1.33, 1.34 Última actualización: February 19, 2026
Kubernetes es una plataforma diseñada pensando en la extensibilidad, lo que permite extender su funcionalidad de diversas maneras. En este capítulo, exploraremos los distintos métodos para extender Kubernetes y cómo aprovechar las características de extensión en Amazon EKS.
Table of Contents
- Kubernetes Extension Overview
- Custom Resources
- Operator Pattern
- Admission Controllers
- API Server Extensions
- Scheduler Extensions
- Cloud Controller Manager
- CSI (Container Storage Interface)
- CNI (Container Network Interface)
- Device Plugins
- Extension Features in Amazon EKS
- Best Practices
- Conclusion
Kubernetes Extension Overview
Kubernetes proporciona varios puntos de extensión para ampliar y personalizar su funcionalidad base. Los principales puntos de extensión son:
- Custom Resources: Definen nuevos tipos de objetos de API
- Operators: Combinan custom resources y controllers para gestionar aplicaciones complejas
- Admission Controllers: Interceptan, modifican o validan solicitudes de API
- API Server Extensions: Agregan nuevos endpoints al API server
- Scheduler Extensions: Personalizan la lógica de scheduling de Pod
- Cloud Controller Manager: Integra características específicas del proveedor de nube
- CSI (Container Storage Interface): Integra sistemas de almacenamiento
- CNI (Container Network Interface): Integra soluciones de red
- Device Plugins: Integran hardware especial
El siguiente diagrama muestra los principales puntos de extensión en Kubernetes:
Choosing an Extension Method
Consideraciones al elegir un método de extensión apropiado:
- Caso de uso: El tipo de funcionalidad que desea extender
- Complejidad: Complejidad de implementación y mantenimiento
- Impacto en el rendimiento: Impacto de la extensión en el rendimiento del clúster
- Compatibilidad de actualización: Compatibilidad con actualizaciones de versión de Kubernetes
- Soporte de la comunidad: Nivel de soporte de la comunidad para el método de extensión
Custom Resources
Los custom resources son una forma de extender la API de Kubernetes para definir nuevos tipos de objetos.
El siguiente diagrama muestra cómo funcionan los custom resources:
Custom Resource Definitions (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 schema del recurso y las columnas adicionales de impresión.
Creating Custom Resource Instances
Después de definir un CRD, puede crear instancias de recursos de ese tipo:
apiVersion: example.com/v1
kind: Backup
metadata:
name: daily-backup
spec:
source: /data
destination: s3://my-bucket/backups
schedule: "0 0 * * *"Custom Resource Validation
Puede validar custom resources usando schemas de OpenAPI v3 en CRDs:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
replicas:
type: integer
minimum: 1
maximum: 10
image:
type: string
pattern: '^[a-zA-Z0-9./:_-]+$'
required:
- replicas
- imageEn el ejemplo anterior, el campo replicas debe ser un entero entre 1 y 10, y el campo image debe coincidir con el patrón especificado.
Version Management
Los CRDs soportan 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 los datos se almacenan en formato v1.
Conversion Webhooks
Puede usar conversion webhooks para manejar conversiones entre diferentes versiones:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: backups.example.com
spec:
# ... other fields omitted ...
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: default
name: example-conversion-webhook
path: /convert
conversionReviewVersions:
- v1Operator Pattern
El operator pattern es una forma de automatizar el conocimiento operacional de aplicaciones complejas combinando custom resources y controllers.
El siguiente diagrama muestra cómo funciona el operator pattern:
Operator Concepts
Un operator consta de los siguientes componentes:
- Custom Resource Definition (CRD): Define el schema de los recursos que se gestionarán
- Controller: Lógica que monitoriza custom resources y los reconcilia con el estado deseado
- Kubernetes API Client: Cliente para interactuar con la API de Kubernetes
Operator Example
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: "13.4"
storageSize: 10Gi
replicas: 3Operator Development Tools
Herramientas para desarrollar operators:
- Operator SDK: Desarrolla operators usando Go, Ansible o Helm
- KUDO (Kubernetes Universal Declarative Operator): Desarrolla operators de forma declarativa
- Kubebuilder: Framework de desarrollo de operators basado en Go
- Metacontroller: Desarrollo de operators basado en webhooks
Operator SDK Example
Creación de un operator usando Operator SDK:
# Install Operator SDK
curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.16.0/operator-sdk_linux_amd64
chmod +x operator-sdk_linux_amd64
mv operator-sdk_linux_amd64 /usr/local/bin/operator-sdk
# 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
make deployPopular Operators
Operators open source populares:
- Prometheus Operator: Gestiona el stack de monitorización Prometheus
- Elasticsearch Operator: Gestiona clústeres de Elasticsearch
- etcd Operator: Gestiona clústeres de etcd
- PostgreSQL Operator: Gestiona bases de datos PostgreSQL
- Jaeger Operator: Gestiona el sistema de distributed tracing Jaeger
- Strimzi Kafka Operator: Gestiona clústeres de Apache Kafka
- Istio Operator: Gestiona Istio service mesh
Admission Controllers
Los admission controllers son plugins que interceptan solicitudes al Kubernetes API server y las modifican o validan.
El siguiente diagrama muestra cómo funcionan los admission controllers:
Admission Controller Types
Kubernetes tiene dos tipos de admission controllers:
- Mutating Admission Controllers: Pueden modificar recursos
- Validating Admission Controllers: Solo pueden validar recursos
Built-in Admission Controllers
Kubernetes tiene varios admission controllers integrados:
- NamespaceLifecycle: Impide la creación de recursos en namespaces que se están eliminando
- LimitRanger: Establece límites de recursos predeterminados para Pods y containers
- ServiceAccount: Crea automáticamente service accounts y agrega tokens
- DefaultStorageClass: Asigna la storage class predeterminada a PVCs
- ResourceQuota: Limita el uso de recursos por namespace
- PodSecurityPolicy: Aplica pod security policies
- NodeRestriction: Limita los recursos que los nodes pueden modificar
Webhook Admission Controllers
Puede usar webhook admission controllers 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", "v1beta1"]
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", "v1beta1"]
sideEffects: None
timeoutSeconds: 5Webhook Server Implementation
Un webhook server debe implementar endpoints como los siguientes:
// Mutating webhook example
func mutateHandler(w http.ResponseWriter, r *http.Request) {
var body []byte
if r.Body != nil {
if data, err := ioutil.ReadAll(r.Body); err == nil {
body = data
}
}
// Convert to AdmissionReview object
admissionReview := v1.AdmissionReview{}
if err := json.Unmarshal(body, &admissionReview); err != nil {
http.Error(w, "Could not parse admission review request", http.StatusBadRequest)
return
}
// Extract Pod object
pod := corev1.Pod{}
if err := json.Unmarshal(admissionReview.Request.Object.Raw, &pod); err != nil {
http.Error(w, "Could not parse pod object", http.StatusBadRequest)
return
}
// Create patch
patches := []map[string]interface{}{
{
"op": "add",
"path": "/metadata/labels/injected-by",
"value": "mutating-webhook",
},
}
patchBytes, _ := json.Marshal(patches)
// Create response
admissionResponse := v1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: true,
Patch: patchBytes,
PatchType: func() *v1.PatchType {
pt := v1.PatchTypeJSONPatch
return &pt
}(),
}
admissionReview.Response = &admissionResponse
resp, _ := json.Marshal(admissionReview)
w.Header().Set("Content-Type", "application/json")
w.Write(resp)
}// Validating webhook example
func validateHandler(w http.ResponseWriter, r *http.Request) {
var body []byte
if r.Body != nil {
if data, err := ioutil.ReadAll(r.Body); err == nil {
body = data
}
}
// Convert to AdmissionReview object
admissionReview := v1.AdmissionReview{}
if err := json.Unmarshal(body, &admissionReview); err != nil {
http.Error(w, "Could not parse admission review request", http.StatusBadRequest)
return
}
// Extract Pod object
pod := corev1.Pod{}
if err := json.Unmarshal(admissionReview.Request.Object.Raw, &pod); err != nil {
http.Error(w, "Could not parse pod object", http.StatusBadRequest)
return
}
// Validation logic
allowed := true
var message string
for _, container := range pod.Spec.Containers {
if container.Image == "nginx:latest" {
allowed = false
message = "Using 'latest' tag is not allowed. Please specify a version."
break
}
}
// Create response
admissionResponse := v1.AdmissionResponse{
UID: admissionReview.Request.UID,
Allowed: allowed,
}
if !allowed {
admissionResponse.Result = &metav1.Status{
Message: message,
}
}
admissionReview.Response = &admissionResponse
resp, _ := json.Marshal(admissionReview)
w.Header().Set("Content-Type", "application/json")
w.Write(resp)
}Popular Admission Controller Projects
- OPA Gatekeeper: Aplicación de políticas usando 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
API Server Extensions
Las API server extensions son una forma de agregar nuevos endpoints al Kubernetes API server.
Extension API Servers
Los extension API servers son servidores que se ejecutan por separado del Kubernetes API server y proporcionan APIs 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>Extension API Server Implementation
Un extension API server consta de los siguientes componentes:
- API Server: Proporciona una interfaz similar al Kubernetes API server
- Resource Handlers: Maneja solicitudes para tipos de recursos específicos
- Storage Backend: Almacena datos de recursos
// 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(
samplev1alpha1.GroupName,
apiserver.Scheme,
metav1.ParameterCodec,
apiserver.Codecs,
)
// Set storage
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = 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)
}
}Aggregation Layer
La aggregation layer hace que varios API servers parezcan un único API server:
+-----------------+
| |
| kube-apiserver |
| |
+-------+---------+
|
v
+--------------------+--------------------+
| |
| |
+-----------v-----------+ +------------v------------+
| | | |
| metrics-server | | example-apiserver |
| | | |
+-----------------------+ +-------------------------+Scheduler Extensions
Las scheduler extensions son una forma de personalizar el comportamiento del Kubernetes scheduler.
Scheduler Framework
El scheduler framework introducido en Kubernetes 1.15 permite extender varias etapas del pipeline de scheduling mediante plugins:
- Queue Sort: Ordena Pods en la cola de scheduling
- Pre-filter: Verifica el estado del Pod y del clúster antes de filtrar
- Filter: Filtra nodes que no pueden ejecutar el Pod
- Post-filter: Realiza acciones después del filtrado
- Pre-score: Realiza acciones antes del cálculo de puntuación
- Score: Asigna puntuaciones a los nodes
- Normalize Score: Normaliza puntuaciones
- Reserve: Reserva recursos para el Pod
- Permit: Permite, deniega o retrasa el scheduling del Pod
- Pre-bind: Realiza acciones antes del binding
- Bind: Vincula el Pod a un node
- Post-bind: Realiza acciones después del binding
Scheduler Configuration
Ejemplo de configuración del scheduler:
apiVersion: kubescheduler.config.k8s.io/v1beta1
kind: KubeSchedulerConfiguration
leaderElection:
leaderElect: true
clientConnection:
kubeconfig: /etc/kubernetes/scheduler.conf
profiles:
- schedulerName: default-scheduler
plugins:
queueSort:
enabled:
- name: PrioritySort
preFilter:
enabled:
- name: NodeResourcesFit
- name: NodePorts
- name: PodTopologySpread
- name: InterPodAffinity
- name: VolumeBinding
- name: NodeAffinity
filter:
enabled:
- name: NodeUnschedulable
- name: NodeName
- name: TaintToleration
- name: NodeAffinity
- name: NodePorts
- name: NodeResourcesFit
- name: VolumeRestrictions
- name: EBSLimits
- name: GCEPDLimits
- name: NodeVolumeLimits
- name: AzureDiskLimits
- name: VolumeBinding
- name: VolumeZone
- name: PodTopologySpread
- name: InterPodAffinity
postFilter:
enabled:
- name: DefaultPreemption
preScore:
enabled:
- name: InterPodAffinity
- name: PodTopologySpread
- name: TaintToleration
- name: NodeAffinity
score:
enabled:
- name: NodeResourcesBalancedAllocation
weight: 1
- name: ImageLocality
weight: 1
- name: InterPodAffinity
weight: 1
- name: NodeResourcesFit
weight: 1
- name: NodeAffinity
weight: 1
- name: PodTopologySpread
weight: 2
- name: TaintToleration
weight: 1
reserve:
enabled:
- name: VolumeBinding
permit:
enabled: []
preBind:
enabled:
- name: VolumeBinding
bind:
enabled:
- name: DefaultBinder
postBind:
enabled: []Custom Scheduler
También puede implementar su propio scheduler para ejecutarlo junto con Kubernetes:
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
containers:
- name: custom-scheduler
image: example/custom-scheduler:v1.0.0
command:
- /custom-scheduler
- --kubeconfig=/etc/kubernetes/scheduler.conf
volumeMounts:
- name: kubeconfig
mountPath: /etc/kubernetes/scheduler.conf
readOnly: true
volumes:
- name: kubeconfig
hostPath:
path: /etc/kubernetes/scheduler.conf
type: FileEspecificar un scheduler personalizado para un Pod:
apiVersion: v1
kind: Pod
metadata:
name: custom-scheduled-pod
spec:
schedulerName: custom-scheduler
containers:
- name: container
image: nginxCloud Controller Manager
El cloud controller manager proporciona una interfaz entre Kubernetes y los proveedores de nube.
Cloud Controller Manager Components
El cloud controller manager consta de los siguientes controllers:
- Node Controller: Actualiza la información de Node mediante APIs del proveedor de nube
- Route Controller: Configura rutas en redes cloud
- Service Controller: Crea, actualiza y elimina load balancers cloud
AWS Cloud Controller Manager
Ejemplo de configuración de AWS Cloud Controller Manager:
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-cloud-controller-manager
namespace: kube-system
data:
cloud.conf: |
[global]
zone = us-east-1a
vpc = vpc-xxx
subnet-id = subnet-xxx
role-arn = arn:aws:iam::xxx:role/xxx
kubernetes.io/cluster/my-cluster = owned
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: aws-cloud-controller-manager
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: aws-cloud-controller-manager
template:
metadata:
labels:
k8s-app: aws-cloud-controller-manager
spec:
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- key: node.cloudprovider.kubernetes.io/uninitialized
value: "true"
effect: NoSchedule
- key: node-role.kubernetes.io/master
effect: NoSchedule
serviceAccountName: cloud-controller-manager
containers:
- name: aws-cloud-controller-manager
image: k8s.gcr.io/cloud-controller-manager:v1.21.0
command:
- /usr/local/bin/cloud-controller-manager
- --cloud-provider=aws
- --cloud-config=/etc/kubernetes/cloud.conf
- --use-service-account-credentials
- --allocate-node-cidrs=false
volumeMounts:
- name: cloud-config
mountPath: /etc/kubernetes/cloud.conf
readOnly: true
volumes:
- name: cloud-config
configMap:
name: aws-cloud-controller-managerCSI (Container Storage Interface)
CSI proporciona una interfaz estándar entre Kubernetes y los sistemas de almacenamiento.
El siguiente diagrama muestra la arquitectura y operación de CSI:
CSI Architecture
CSI consta de los siguientes componentes:
- CSI Controller Plugin: Maneja la creación, eliminación, snapshots de volúmenes, etc.
- CSI Node Plugin: Maneja el montaje y 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 |
| |
+-------------------+CSI Driver Deployment
Ejemplo de deployment de CSI driver:
# 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
containers:
- name: csi-provisioner
image: k8s.gcr.io/sig-storage/csi-provisioner:v2.1.0
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: k8s.gcr.io/sig-storage/csi-attacher:v3.1.0
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
hostNetwork: true
containers:
- name: csi-node-driver-registrar
image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.1.0
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: DirectoryStorage Class and PVC
Ejemplo de storage class y PVC usando CSI driver:
# Storage Class
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: example-csi
provisioner: example.csi.k8s.io
parameters:
type: ssd
fsType: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
volumeBindingMode: Immediate
# PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: example-csiPopular CSI Drivers
- 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 persistent disks 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 networking.
El siguiente diagrama muestra la arquitectura y operación de CNI:
CNI Architecture
CNI consta de los siguientes componentes:
- CNI Plugin: Configura interfaces de red de containers
- IPAM Plugin: Asignación y gestión de direcciones IP
- Meta Plugin: Combina varios plugins juntos
+-------------------+
| |
| Kubernetes |
| (kubelet) |
| |
+--------+----------+
|
| CNI Spec
v
+--------+----------+
| |
| CNI Plugin |
| |
+--------+----------+
|
| Network Configuration
v
+--------+----------+
| |
| Network |
| |
+-------------------+CNI Plugin Configuration
Ejemplo de configuración de CNI plugin:
{
"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" }
]
}
}Popular CNI Plugins
- Calico: CNI con network policy mejorada y características de seguridad
- Flannel: Proporciona networking overlay simple
- Cilium: Solución de networking y seguridad basada en eBPF
- Weave Net: Solución de networking de containers multi-host
- AWS VPC CNI: CNI integrado con AWS VPC
- Azure CNI: CNI integrado con redes virtuales de Azure
- Antrea: Solución de networking basada en Open vSwitch
CNI Plugin Installation
Ejemplo de instalación del Calico CNI plugin:
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yamlDevice Plugins
Los device plugins proporcionan una interfaz entre Kubernetes y hardware especial.
Device Plugin Architecture
Los device plugins constan de los siguientes componentes:
- Device Plugin Server: Maneja el descubrimiento, la asignación, la inicialización de dispositivos, etc.
- kubelet: Se comunica con 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 deployment del NVIDIA GPU device plugin:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nvidia-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: nvidia-device-plugin-ds
template:
metadata:
labels:
name: nvidia-device-plugin-ds
spec:
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
containers:
- name: nvidia-device-plugin-ctr
image: nvidia/k8s-device-plugin:v0.9.0
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-pluginsGPU Request Pod
Ejemplo de Pod que solicita GPU:
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
containers:
- name: cuda-container
image: nvidia/cuda:11.0-base
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1Popular Device Plugins
- 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
Extension Features in Amazon EKS
Amazon EKS soporta varias características de extensión para extender la funcionalidad del clúster de Kubernetes.
El siguiente diagrama muestra la arquitectura de características de extensión en Amazon EKS:
EKS Add-ons
Amazon EKS proporciona los siguientes add-ons:
- Amazon VPC CNI: Networking integrado 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: Gestión de load balancers de AWS
# List EKS add-ons
aws eks list-addons --cluster-name my-cluster
# Install EKS add-on
aws eks create-addon \
--cluster-name my-cluster \
--addon-name amazon-ebs-csi-driver \
--service-account-role-arn arn:aws:iam::123456789012:role/AmazonEKS_EBS_CSI_DriverRole
# Update EKS add-on
aws eks update-addon \
--cluster-name my-cluster \
--addon-name amazon-ebs-csi-driver \
--addon-version v1.5.0-eksbuild.1
# Delete EKS add-on
aws eks delete-addon \
--cluster-name my-cluster \
--addon-name amazon-ebs-csi-driverAWS Controllers for Kubernetes (ACK)
ACK es una colección de operators que permite gestionar recursos de AWS desde Kubernetes:
# Install ACK controller
helm repo add ack-controller https://aws.github.io/aws-controllers-k8s
helm install ack-s3-controller ack-controller/s3-chart
# Create S3 bucket
cat <<EOF | kubectl apply -f -
apiVersion: s3.services.k8s.aws/v1alpha1
kind: Bucket
metadata:
name: my-bucket
spec:
name: my-bucket-123456
EOFAWS Load Balancer Controller
El AWS Load Balancer Controller integra services e ingresses de Kubernetes con load balancers de AWS:
# ALB Ingress example
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
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 service accounts de Kubernetes:
# Create OIDC provider
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 arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approve
# Pod using service account
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: s3-reader
spec:
serviceAccountName: my-service-account
containers:
- name: aws-cli
image: amazon/aws-cli:latest
command:
- sleep
- "3600"
EOFBest Practices
Exploremos las mejores prácticas que se deben considerar al implementar características de extensión de Kubernetes.
Design Best Practices
- Usar interfaces estándar: Use interfaces estándar como CSI y CNI cuando sea posible
- Diseño de API declarativa: Diseñe APIs declarativas en lugar de imperativas
- Seguir los principios de diseño de Kubernetes: Siga principios como el controller pattern y level-triggering
- Gestión de versiones: Gestione las versiones de API y mantenga la compatibilidad
- Principio de mínimo privilegio: Conceda solo los permisos mínimos necesarios
Implementation Best Practices
- Aprovechar librerías reutilizables: Aproveche librerías como client-go y controller-runtime
- Manejo adecuado de errores: Manejo y logging adecuados para situaciones de error
- Exponential Backoff: Use exponential backoff para los reintentos
- Establecer límites de recursos: Establezca límites de memoria y CPU
- Reporte de estado: Informe el estado de los recursos con precisión
Deployment Best Practices
- Despliegue gradual: Despliegue gradualmente en lugar de cambiar todo de una vez
- Gestión de versiones: Evite usar la etiqueta latest para las imágenes
- Health Checks: Configure liveness y readiness probes apropiados
- Logging y monitorización: Configure logging y monitorización completos
- Documentación: Documente APIs y uso
Security Best Practices
- Principio de mínimo privilegio: Conceda solo los permisos mínimos necesarios
- Usar RBAC: Configure políticas RBAC apropiadas
- Network Policies: Configure network policies apropiadas
- Image Scanning: Escanee imágenes de container en busca de vulnerabilidades
- Secret Management: Gestione secrets de forma segura
EKS-Specific Best Practices
- Usar Managed Add-ons: Use add-ons gestionados de 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 networking
- Security Groups: Configure security groups apropiados
- Optimización de costos: Seleccione tipos y tamaños de instancia apropiados
Conclusion
Kubernetes proporciona varios puntos de extensión para extender y personalizar su funcionalidad base. Custom resources, operators, admission controllers, API server extensions, scheduler extensions, CSI, CNI y device plugins le permiten adaptar Kubernetes a diversos entornos y requisitos.
Amazon EKS soporta estas características de extensión y además proporciona características específicas de AWS como EKS add-ons, 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 mejores prácticas como usar interfaces estándar, diseño de API declarativa y el principio de mínimo privilegio. Esto permite crear entornos de Kubernetes estables y escalables.
Quiz
Para comprobar lo que aprendió en este capítulo, pruebe el Extending Kubernetes Quiz.