Kubernetes in Depth — Storage, Security, and Advanced Features
Storage in Kubernetes
Kubernetes offers robust storage mechanisms to manage persistent application data. From temporary volumes to persistent volumes, Kubernetes ensures reliability and scalability for production clusters. Let’s dive into how storage works and why it’s critical for your apps.
Volumes and Volume Types
A Pod specification defines one or more volumes, specifying their name, type, and mount point. Volumes allow data sharing among containers within a Pod or across multiple Pods with defined access modes. Kubernetes supports various volume types, each suited for specific use cases:
emptyDir: A temporary directory created when a Pod starts and erased when it terminates. It’s recreated on container restarts, perfect for transient data like caches.
hostPath: Mounts a resource (directory, file socket, etc.) from the host node’s filesystem. Great for local testing, but avoid in production due to node-specific risks.
NFS and iSCSI: Support multiple readers, ideal for shared read-only access.
rbd, CephFS, GlusterFS: Enable multiple writers, suitable for distributed apps needing concurrent write access.
GCEPersistentDisk, awsElasticBlockStore: Integrate with Google Cloud and AWS storage. Note: These in-tree plugins are being replaced by Container Storage Interface (CSI) drivers in Kubernetes 1.31 for better extensibility (learn more).
Kubernetes Pod Volumes
Pods request volumes with specific access modes. The cluster matches the request, grouping volumes by mode and sorting by size (smallest to largest). The kubelet maps devices, creates mount points, and links storage to containers via the host filesystem. StorageClass plugins handle backend specifics.
The three access modes are:
ReadWriteOnce: Read-write access by a single node. Two Pods on the same node can write, but a third on another node triggers a FailedAttachVolume error.
ReadOnlyMany: Read-only access by multiple nodes.
ReadWriteMany: Read-write access by multiple nodes.
When a volume is requested, the cluster matches the Pod’s access mode, grouping volumes by mode and sorting them by size (smallest to largest). The kubelet, via the kubelet_pods.go script, maps raw devices, creates mount points, and establishes symbolic links on the host filesystem to associate storage with containers. The API server interacts with StorageClass plugins to fulfill requests, with specifics varying by backend storage.
The following YAML creates a Pod named exampleA with two containers sharing an emptyDir volume:
apiVersion: v1 kind: Pod metadata: name: exampleA spec: containers: - name: alphacont image: busybox volumeMounts: - mountPath: /alphadir name: sharevol - name: betacont image: busybox volumeMounts: - mountPath: /betadir name: sharevol volumes: - name: sharevol emptyDir: {}
Verify shared access:
kubectl exec -ti exampleA -c betacont -- touch /betadir/foobar kubectl exec -ti exampleA -c alphacont -- ls -l /alphadir # Output: total 0 -rw-r--r-- 1 root root 0 foobar
Persistent Volume Claim
Persistent Volumes (PVs) abstract storage to retain data beyond a Pod’s lifecycle. Pods request storage via Persistent Volume Claims (PVCs), specifying size and StorageClass. The cluster dynamically attaches a matching PV, often using CSI drivers in modern setups.
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes: - ReadWriteOnce resources: requests: storage: 8Gi
In the Pod:
spec: containers: - name: myapp image: myapp volumeMounts: - name: test-volume mountPath: "/data" volumes: - name: test-volume persistentVolumeClaim: claimName: myclaim
Security in Kubernetes
Kubernetes secures clusters through robust access control and data protection mechanisms. Security in production environments relies on safeguarding sensitive data and controlling API access to prevent unauthorized actions and ensure compliance.
Secrets Management
Secrets store sensitive data (e.g., passwords, keys) in base64-encoded format to avoid plain-text exposure. They’re created via kubectl or YAML and used as environment variables or mounted volumes. Note: For demo purposes, we use MySecurePass123. In production, use strong, unique passwords and enable encryption at rest or tools like Sealed Secrets.
Creating Secrets
Secrets can be generated using kubectl:
kubectl create secret generic mysql --from-literal=password=MySecurePass123
Alternatively, manual creation involves base64-encoding data in a YAML manifest:
echo -n MySecurePass123 | base64 # Output: TXlTZWN1cmVQYXNzMTIz
apiVersion: v1 kind: Secret metadata: name: mysql data: password: TXlTZWN1cmVQYXNzMTIz
Secrets are not encrypted by default, only base64-encoded, requiring additional measures like encryption at rest for enhanced security. Each Secret is limited to 1MB, and excessive use can strain host memory, as Secrets are stored as API objects.
Using Secrets as Environment Variables
Secrets can be injected into containers as environment variables:
apiVersion: v1 kind: Pod metadata: name: dbpod spec: containers: - image: mysql:8.0 name: dbpod env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql key: password
This configuration securely passes the password to the MySQL container without exposing it in plain text.
Mounting Secrets as Volumes
Secrets can be mounted as files within a container, providing an alternative access method:
apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: myapp image: busybox command: ["sleep", "3600"] volumeMounts: - mountPath: /mysqlpassword name: mysql volumes: - name: mysql secret: secretName: mysql
Verify access:
kubectl exec -ti example-pod -- cat /mysqlpassword/password # Output: MySecurePass123
Mounting Secrets as volumes creates files named after the Secret’s keys, readable only by the container, enhancing data isolation.
API Security
Kubernetes secures API access through authentication, authorization, and admission control.
Authentication
Methods include:
X.509 certificates: For client authentication, often managed by kubeadm.
Service Accounts: Identities for Pods to interact with the API.
OpenID Connect: For external identity providers.
Unauthenticated requests are rejected early.
Authorization
Policies evaluate requests via:
Role-Based Access Control (RBAC): Dominant in 1.31, using Roles and RoleBindings for granular permissions.
Attribute-Based Access Control (ABAC): Less common, attribute-based.
Node Authorization: Limits kubelet to node-specific resources.
Admission Controllers
These validate/modify API objects before persistence, enforcing policies like resource limits or image validation. Examples: LimitRanger, PodSecurityAdmission (replacing PodSecurityPolicy in 1.31).
TLS Encryption
All API requests use TLS, configured by kubeadm. Invalid SSL certificates block access, ensuring secure communication.Advanced Features
Kubernetes advanced features enhance the management of complex applications. These capabilities, including configuration management and sophisticated HTTP routing, provide flexibility and scalability for production workloads.
ConfigMaps for Configuration
ConfigMaps decouple configuration data from container images for dynamic application management. ConfigMaps store non-sensitive data as key-value pairs or configuration files, enabling Pods to access settings without hardcoding. They are created via kubectl or YAML manifests and used as environment variables, command arguments, or volume mounts.
Creating ConfigMaps
ConfigMaps can encapsulate configuration files, such as config.js:
kubectl create configmap foobar --from-file=config.js
The resulting YAML:
apiVersion: v1 kind: ConfigMap metadata: name: foobar data: config.js: | { "key": "value" }
Retrieve with:
kubectl get configmap foobar -o yaml
ConfigMaps can also be populated from literal values or directories, supporting diverse configuration needs.
Using ConfigMaps
ConfigMaps are consumed in Pods in several ways:
Environment Variables: Inject values into containers:
apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: myapp image: myapp env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how
Command Arguments: Pass values to container commands (not shown in the provided excerpt but supported).
Volume Mounts: Mount ConfigMaps as files:
apiVersion: v1 kind: Pod metadata: name: config-pod spec: containers: - name: myapp image: myapp volumeMounts: - name: config-volume mountPath: "/etc/config" volumes: - name: config-volume configMap: name: special-config
ConfigMaps must exist in the same namespace as the Pod before deployment, unless marked optional. They support complex configurations, such as populating volumes with specific paths or access modes, enhancing application portability.
Ingress for HTTP Routing
Ingress enables centralized HTTP and HTTPS routing to cluster services. Unlike Service Types (ClusterIP, NodePort, LoadBalancer, ExternalName), Ingress routes traffic based on request host or path, reducing reliance on external load balancers. It requires an Ingress Controller to process routing rules.
Ingress Controllers
Ingress Controllers, such as Nginx or Traefik, run as Pods and monitor the /ingresses endpoint in the networking.k8s.io/v1 API group. They apply Ingress Rules to direct external traffic to Services, typically over HTTP. Multiple controllers can coexist, with annotations specifying which controller handles a given Ingress:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: my-service port: number: 80
Without a matching annotation, all controllers may attempt to process the Ingress, potentially causing conflicts.
Ingress Rules
Ingress Rules define how traffic is routed based on URL paths or hostnames. The above example routes requests to example.com/ to my-service on port 80. Path types (Prefix, Exact, ImplementationSpecific) provide granular control, while annotations like rewrite-target modify request paths for compatibility.
Ingress centralizes access to multiple Services, improving efficiency in large clusters. It integrates seamlessly with cloud-native environments, supporting production-grade HTTP routing as of Kubernetes 1.30.
Kubernetes streamlines data persistence and access control for robust application deployment. Advanced routing and configuration mechanisms enhance cluster flexibility. Mastery of these capabilities drives efficient management of production systems.
Made by a Human