Kubernetes Storage and Kubernetes Security

Kubernetes Storage and Kubernetes Security

#Day5 - #KubeWeek challenge

Table of contents

No heading

No headings in the article.

What is Kubernetes Storage?

Kubernetes storage is useful for storage administrators because it allows them to maintain multiple forms of persistent and non-persistent data in a Kubernetes cluster. This makes it possible to create dynamic storage resources that can serve different types of applications.

If properly managed, the Kubernetes storage framework can be used to automatically provision the most appropriate storage to multiple applications, with minimal administrative overhead.

Kubernetes Storage Concepts

Containers use the principle of immutability. This means that when containers are destroyed, including all data created during the lifetime of the containers. Immutability is not always appropriate, however.

Kubernetes supports multiple types of persistent storage. This can include file, block, or object storage services from cloud providers (such as Amazon S3), storage devices in the local data centre, or data services like databases. Kubernetes provides mechanisms to abstract this storage for applications running on containers so that applications never communicate directly with storage media.

Container Storage Interface (CSI)

CSI is a Kubernetes extension that simplifies storage management. CSI provides an extensible plugin architecture, so you can easily add plugins that support the storage devices and services used in your organization.

Volumes

Volumes are basic entities in Kubernetes, used to provide storage to containers. A volume can support all types of storage, including network file systems (NFS), local storage devices, and cloud-based storage services. You can also build your own storage plugins to support new storage systems. Access to volumes can be achieved directly via pods or through persistent volumes (explained below).

Non-Persistent Storage (Ephemeral)

The default storage configuration in Kubernetes is non-persistent (Ephemeral). As long as a container exists, it stores data in the temporary storage directory of the host, and when it shuts down the data is removed.

Persistent Volumes (PV) and Persistent Volume Claims (PVC)

To enable persistent storage, Kubernetes uses two key concepts:

PersistentVolume (PV) is a storage element in a cluster, defined manually by an administrator or dynamically defined by a storage class (explained below). A PV has its own lifecycle, separate from the lifecycle of Kubernetes pods. The PV API captures storage implementation details for NFS, cloud provider-specific storage systems, or iSCSI.

i.e. PersistentVolume (PV)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongo-pv
spec:
  capacity:
    storage: 256Mi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/db

PersistentVolumeClaim (PVC) is a user’s storage request. An application running on a container can request a certain type of storage.

Users can request storage based on these custom parameters without knowing the implementation details of the underlying storage. This is achieved using the StorageClass resource.

i.e. PersistentVolume (PVC)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongo-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 256Mi

StorageClasses

A StorageClass represents one type of storage. For example, one StorageClass may represent fast SSD storage, while another can represent magnetic drives, or remote cloud storage. This allows Kubernetes clusters to configure various types of storage according to workload requirements.

A StorageClass is a Kubernetes API for setting storage parameters using dynamic configuration to enable administrators to create new volumes as needed. The StorageClass defines the volume plug-in, external provider (if applicable), and the name of the container storage interface (CSI) driver that will enable containers to interact with the storage device.

Dynamic Provisioning of StorageClasses

Kubernetes supports dynamic volume configuration, allowing you to create storage volumes on demand. Therefore, administrators do not have to manually create new storage volumes and then create a PersistentVolume object for use in the cluster. When the user requests a specific type of storage, the entire process runs automatically.

The cluster administrator defines storage class objects as needed. Each StorageClass refers to a volume plugin, also called a provisioner.

Kubernetes Security

Kubernetes is extremely powerful, it also raises new security concerns that traditional approaches and tools cannot solve.

Kubernetes workloads are vulnerable to several types of security threats, including:

  • Compromise of the Kubernetes control plane - critical components like etcd and the API Server is not sufficiently secured by default. An attacker gaining access to a Kubernetes master node can gain control of an entire cluster.

  • Compromise of nodes and pods - an attacker can gain access to a physical host running several Kubernetes pods, or to an individual pod, enabling exfiltration of data within the pods, and lateral movement to other parts of the cluster.

  • Compromise of network connections - unless Kubernetes is configured securely, containers and pods may be able to freely connect to each other and may be exposed to the public Internet. Any such open connections are an entry point for attackers.

  • Compromise of containers - individual containers can become vulnerable, due to a vulnerability or backdoor in a container image, or a misconfiguration. Containers with excess privileges can allow attackers access to the physical host.

Kubernetes Security Concepts

Here are a few key concepts you need to know as you plan your Kubernetes security strategy. The Four Cs of Cloud Native Security:

  • Code

  • Container

  • Cluster

  • Cloud

At each level, security best practices should be followed. There may be different security considerations at different levels. For example:

  • At the code level, you can ensure all data being transferred is encrypted

  • At the container level, you can restrict access to network ports

  • At the cluster level, you can harden cluster components like etcd

  • At the cloud level, you can set up robust identity and access management (IAM)

These are just examples of security concerns that may exist at each level of the 4C model

Pod Security Policies

There are three default security policies for Kubernetes pods. To properly protect your environment, you need to understand the tradeoff between availability and security.

  • Privileged - the highest level of authority. If the pod is compromised, this may allow an attacker to escalate privileges. Baseline—prevents escalation of known privileges.

  • Restricted - the recommended setting according to Kubernetes pod hardening best practices.

Pod Security Context

The pod security context configures security settings at runtime. This includes aspects such as access control, whether to run in privileged mode or not, and mounting read-only file systems.

The difference between security policies and the security context is that policies define security parameters, and the context is what executes policies at runtime.

Secrets

You should never put an authentication token or password in a YAML configuration file. Kubernetes provides a mechanism called secrets, for storing this type of sensitive information.

Keep in mind that Kubernetes secrets are not secured by default. You can and should enable encryption for secrets, and set RBAC rules defining who can read or write the secret.

Enable Role-Based Access Control (RBAC)

Role-Based Access Control (RBAC) regulates access and permissions to the Kubernetes API. Configuration settings, however, should be checked after upgrading. Legacy Attribute-Based Access Control (ABAC) should be disabled when enabling RBAC.

After enforcing RBAC, namespace-specific permissions should be favoured over cluster-wide permissions. Cluster-admin privileges should only be granted on a case-by-case basis, even while debugging.

i.e. RBAC

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-group
  namespace: development
subjects:
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

i.e. Network Policies

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: block-specific-pod
spec:
  podSelector:
    matchLabels:
      app: db
  policyTypes:
  - Ingress
  ingress:
  - from:
    - ipBlock:
        cidr: 192.168.0.0/16

i.e. Secrets

$ kubectl create secret generic my-secret \
    --from-literal=username=my-username \
    --from-literal=password=my-password
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: my-image
          env:
            - name: MY_USERNAME
              valueFrom:
                secretKeyRef:
                  name: my-secret
                  key: username
            - name: MY_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: my-secret
                  key: password

i.e. POD Secutiry Policies

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  seLinux:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  volumes:
  - configMap
  - secret
  - emptyDir
  - projected
  - downwardAPI

i.e Image Scaning

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: image-validation-webhook
webhooks:
- name: image-validation.example.com
  rules:
  - apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
    operations: ["CREATE"]
  clientConfig:
    service:
      name: clair
      namespace: clair
      path: /validate

i.e. Network Encryption

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-tls-traffic
spec:
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ns-1
    ports:
    - port: 443
      protocol: TCP
    tls:
      hosts:
      - api.example.com

This was a basic overview of Kubernetes Storage and Kubernetes Security, I hope this content is helpful for your knowledge.