Scalable and Secure Deployment with Kubernetes Storage and Security Features

Amol OvhalAmol Ovhal
9 min read

Kubernetes has become the de facto standard for deploying and managing containerized applications in production. It provides many features to enable scalable and secure deployment of containerized applications. Two critical aspects of Kubernetes are storage and security.


Kubernetes Storage:

Persistent Volumes and Persistent Volume Claims:

Storage in Kubernetes is managed by Persistent Volumes (PVs) and Persistent Volume Claims (PVCs). PVs are abstractions that represent physical storage resources in a cluster. They can be backed by different storage types, such as network-attached storage, local storage, or cloud storage. PVCs are requests for a specific amount and type of storage by a user or a pod.

Storage Classes define different types of storage that can be requested through PVCs. They provide a way for administrators to specify different storage backends, such as storage providers and storage classes. Kubernetes provides default Storage Classes, but administrators can create their custom Storage Classes to fit their specific requirements.

Here's an example manifest for a PersistentVolume:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: my-storage-class
  hostPath:
    path: /mnt/data

This manifest creates a PersistentVolume (PV) named "my-pv" with a capacity of 10GB backed by local storage on the Kubernetes node. It also specifies that the PV can only be mounted by a single node at a time using the ReadWriteOnce access mode and that the PV should be retained when a claim is deleted. The manifest also assigns the PV to the "my-storage-class" StorageClass, which can be used by PersistentVolumeClaims to request storage from this PV. The hostPath field specifies the local path on the Kubernetes node where the PV should store its data.

Here's an example manifest for a PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: my-storage-class

This manifest creates a PersistentVolumeClaim (PVC) named "my-pvc" requesting 5GB of storage from a PersistentVolume that has been assigned to the "my-storage-class" StorageClass. The accessModes field specifies that the PVC requires read-write access to the PV, and the resources.requests.storage field specifies the amount of storage the PVC needs. This PVC can be used by Kubernetes Pods that require persistent storage to mount the assigned PV and store data.

StatefulSets:

StatefulSets are used to manage stateful applications in Kubernetes. StatefulSets enable stateful applications to be deployed and managed in Kubernetes in the same way as stateless applications. They provide features such as ordered deployment, unique network identities, and stable storage.

Here's an example manifest for a Kubernetes StatefulSet:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset
spec:
  serviceName: my-statefulset-service
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: my-volume
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: my-volume
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

This manifest creates a StatefulSet named "my-statefulset" in Kubernetes. The spec field specifies that the StatefulSet should create a set of three replicas of a Pod template. The serviceName field specifies the name of the service that should be used to access the Pods in the StatefulSet.

The template field specifies the Pod template that should be used to create the replicas. In this example, the Pod template includes a single container running the nginx image, with a port exposed on port 80. The volumeMounts field specifies that a volume named "my-volume" should be mounted at /usr/share/nginx/html in the container.

The volumeClaimTemplates field specifies that a PersistentVolumeClaim (PVC) named "my-volume" should be created for each replica. The PVC is set to request 1GB of storage with access mode ReadWriteOnce, meaning it can be mounted by a single Pod at a time.

Kubernetes StatefulSets can be used to deploy and manage stateful applications that require unique network identities and stable persistent storage.


Kubernetes Security:

RBAC (Role-Based Access Control):

Kubernetes provides several security features to ensure the secure deployment of applications. RBAC (Role-Based Access Control) is a feature that enables administrators to define roles and access control policies for users and groups. This allows administrators to restrict access to Kubernetes resources based on a user's role or group membership.

Here's an example manifest for Role-Based Access Control (RBAC):

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

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: my-role
subjects:
- kind: User
  name: my-user
  apiGroup: rbac.authorization.k8s.io

This manifest creates a Role named "my-role" that grants a user or group of users permission to access Pods in the Kubernetes cluster. The rules field specifies the API resources that the role can access and the verbs that are allowed. In this case, the role can get, watch, and list information about Pods.

The manifest also creates a RoleBinding named "my-role-binding" that binds the "my-role" role to a specific user named "my-user". The roleRef field specifies the role that is being bound, and the subjects field specifies the user or group of users that are being granted access to the role. With this manifest, "my-user" can now access Pod resources in the Kubernetes cluster according to the permissions granted by the "my-role" role.

Pod Security Policies (PSPs):

Pod Security Policies (PSPs) is a security feature that enables administrators to enforce security policies on pods. PSPs define a set of security policies that must be met by all pods in a Kubernetes cluster. These policies include restricting the use of privileged containers, enforcing minimum security contexts, and restricting the use of host namespaces and volumes.

Here's an example manifest for Pod Security Policies:

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: my-psp
spec:
  privileged: false
  seLinux:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
  - '*'

---

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: nginx
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  securityContext:
    seLinuxOptions:
      user: "s0"

This manifest creates a PodSecurityPolicy (PSP) named "my-psp" that specifies security restrictions on Pods running in the Kubernetes cluster. The spec field specifies that the PSP does not allow privileged containers, and that any user or group can run the Pod, as well as mount any volume. The volumes field specifies that any volume can be used by the Pod.

The manifest also creates a Pod named "my-pod" that uses the PSP "my-psp". The spec field specifies that the Pod has a single container running the nginx image. The securityContext field specifies that the container should run as a specific user and group, and have a specific file system group. Additionally, the seLinuxOptions field specifies that the SELinux user of the container should be set to "s0". With this manifest, the "my-pod" Pod is restricted by the "my-psp" PSP and can only run with the specified security settings.

Secrets:

Secrets are used to store sensitive data such as passwords, API keys, and certificates. Kubernetes provides Secrets as an API object that can be used to securely store and manage sensitive data. Secrets can be mounted as volumes in pods, and they are encrypted at rest and in transit.

Here's an example manifest for a Kubernetes Secret:

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: dXNlcm5hbWU=
  password: cGFzc3dvcmQ=

This manifest creates a Secret named "my-secret" in Kubernetes. The type field specifies that the secret data is opaque, meaning it could be anything. The data field contains key-value pairs that are base64 encoded. In this example, the key-value pairs are "username" and "password", which are both base64 encoded.

To decode the values, one can use the following commands:

echo 'dXNlcm5hbWU=' | base64 --decode

The above command would output "username".

echo 'cGFzc3dvcmQ=' | base64 --decode

The above command would output "password".

Kubernetes Secrets can be used to store and manage sensitive information such as API keys, passwords, and certificates used by applications running within Kubernetes Pods.

Network Policies:

Network Policies enable administrators to define rules for network traffic within a Kubernetes cluster. Network Policies allow administrators to restrict network traffic between pods based on IP addresses, ports, and protocols.

Here's an example manifest for a Kubernetes NetworkPolicy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
spec:
  podSelector:
    matchLabels:
      app: my-app
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: my-app
    ports:
    - protocol: TCP
      port: 80

This manifest creates a NetworkPolicy named "my-network-policy" in Kubernetes. The spec field specifies that the NetworkPolicy should apply to Pods with the label "app: my-app". The policyTypes field specifies that the NetworkPolicy should apply to incoming traffic (Ingress).

The ingress field specifies that incoming traffic should be allowed from Pods with the label "app: my-app" and that the traffic should be allowed on TCP port 80.

Kubernetes NetworkPolicies can be used to control the flow of network traffic to and from Pods in a Kubernetes cluster. They can be used to enforce security policies and isolate applications from each other.

TLS (Transport Layer Security):

TLS (Transport Layer Security) is a cryptographic protocol used to secure communication over the Internet. Kubernetes provides support for TLS, enabling administrators to secure communication between pods and the Kubernetes API server. Kubernetes also provides support for mutual TLS authentication, enabling both client and server authentication.

here's an example manifest for a Kubernetes TLS (Transport Layer Security):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-ciphers: "ECDHE-RSA-AES128-GCM-SHA256"
    nginx.ingress.kubernetes.io/ssl-protocols: "TLSv1.2"
spec:
  tls:
  - hosts:
    - example.com
    secretName: my-tls-secret
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              name: http

This manifest creates an Ingress resource named "my-ingress" in Kubernetes, which enables TLS encryption on incoming traffic. The annotations field specifies that traffic should be redirected to HTTPS, and specifies the SSL ciphers and protocols that should be used.

The tls field specifies that traffic should be encrypted using a TLS certificate and private key stored in a Kubernetes Secret named "my-tls-secret". The certificate should be valid for the domain name "example.com".

The rules field specifies that incoming traffic for the domain name "example.com" should be directed to the backend service named "my-service", which is listening on port 80 for HTTP traffic.

Kubernetes Ingress resources can be used to manage external access to services running within a Kubernetes cluster, and TLS encryption can be used to secure that traffic.


Conclusion:

Kubernetes provides several features to enable scalable and secure deployment of containerized applications. Storage in Kubernetes is managed by Persistent Volumes and Persistent Volume Claims, Storage Classes, and StatefulSets. Kubernetes Security features include RBAC, Pod Security Policies, Secrets, Network Policies, and TLS. These features provide a solid foundation for the secure deployment of containerized applications in production.


10
Subscribe to my newsletter

Read articles from Amol Ovhal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Amol Ovhal
Amol Ovhal

I'm Amol, a DevOps Engineer who enjoys automation, continuous integration, and deployment. With extensive Hands-on experience in DevOps and Cloud Computing, I am proficient in various tools and technologies related to infrastructure automation, containerization, cloud platforms, monitoring and logging, and CI/CD. My ultimate objective is to assist organisations in achieving quicker, more effective software delivery while maintaining high levels of quality and dependability.