Three primary ways to secure Kubernetes workloads

Brandon Kang
System Weakness
Published in
7 min readMar 30, 2023

--

Kubernetes provides many advantages in deploying, operating, and managing container services by providing the ability to manage numerous containers in an integrated manner.

However, this feature of Kubernetes may also expose applications to security vulnerabilities. In fact, security attacks on containers are on the rise, and the impact is getting more severe. So security is just as important in a Kubernetes environment as it is in any other development or production environment.

Security in the Kubernetes environment means maintaining the stability and security of the Kubernetes cluster. Kubernetes provides basic security features to secure your cluster.

There are many security related features like this.
• Network Security
• Node Security
• Authentication
• Authorization
• Secure image management
• Secrets management
• Logging and monitoring
• Disaster Recovery
• And more…

This article introduces three of the most representative ones. Network policies to control access to Kubernetes clusters, role-based access control (RBAC), and secrets to securely store sensitive information.

1. Control Pods communication with Network Policies

Kubernetes’ communication policy defaults to allowing communication between all pods. While a policy that is useful for communication, it also carries the risk of exposing Pods to unwanted connections. Therefore, if you want to prevent unauthorized access and protect your pods, you should use Network Policy.

A network policy is a feature that controls communication between pods or between pods and other network endpoints. Network policies allow you to define rules that allow or deny traffic based on various criteria such as IP address, port, protocol and labels. In addition, you can set up network policies that only allow traffic from certain namespaces.

Network policies are implemented using the Kubernetes network plugin architecture. Therefore, different network plugins may have different levels of support for network policies.

<Kubernetes Network Policy>

Some popular network plugins such as Calico, Cilium and Weave Net natively support network policies, while others may require additional configuration or custom development.

When setting network policy, three elements are important:

  • podSelector: Specifies the pods to which the policy applies
  • policyTypes: Specifies the traffic to which the policy will be applied. There is ingress traffic and egress traffic
  • ingress/egress: Specifies the details of ingress/egress traffic.

Let’s take a look at these three elements through an example. The example below is a YAML file that sets the network policy. If you look at podSelector in the example, you can see that the database is specified as the pod to which the policy will be applied. And through policyTypes setting, network policy is applied to incoming and outgoing traffic at the same time.

Finally, defining the ingress & egress traffic detailed policy, defining the namespace, pod, protocol and port number, and IP band to allow traffic.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-nwpolicy
namespace: default
spec:
podSelector:
matchLabels:
role: database
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 10.17.0.0/16
- namespaceSelector:
matchLabels:
name: my-ns
- podSelector:
matchLabels:
app: my-pod
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978

Looking at the example above, you can see that it controls inbound and outbound traffic just like a firewall on a web server or a security group on a cloud instance. In this way, through network policies, Kubernetes determines and controls which network requests an application installed in a pod can receive and from where. And by limiting the network traffic of pods in the cluster, you can protect your cluster from various security attacks.

2. Permission with RBAC(Role Based Access Control)

Kubernetes consists of many resources, including services, networking, namespaces, pods, nodes, and containers. Restricting which users and services have access to each resource is critical to keeping your cluster secure.

Role-Based Access Control (RBAC) in Kubernetes controls access to cluster resources by defining roles for users and service accounts and granting permissions based on the roles. You define security rules using Roles, which set roles for users or service accounts, and ClusterRole, which set roles at the cluster level, and add these rules to Groups, which are collections of users.

Role-based access control consists of three main concepts:

  • Role: A role is a set of privileges that grants access to cluster resources. For example, you could define a role called ‘pod-reader’ and grant read access to all pods within the same namespace
  • RoleBinding: Assign a role to a specific user or service account. In other words, it is a function that binds roles and accounts. For example, attach the ‘pod-reader’ role to user ‘user-1’ so that user ‘user-1’ can read all pods within the same namespace
  • ClusterRole: Similar to Role, but with different scope of permissions. A Role assigns privileges that are valid only within a specific namespace, whereas a ClusterRole assigns privileges that are valid cluster-wide. It requires a ClusterRoleBinding that defines the association between a ClusterRole and a user or service account

Looking at the image below, role-based access control can be seen at a glance.

<Role in a namespace and ClusterRole in the K8s Cluster>

Let’s look at role-based access control with an example as well. The example below is a YAML file that defines a role named dev-team.

<role.yaml>

apiVersion: rbac.authorization.k8s.io/v1    
kind: Role
metadata:
namespace: development
name: dev-team
rules:
- apiGroups: ["core", "extensions", "apps"]
resources: ["deployments", "replicasets", "pods"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

This role specifies the tasks and targets that a specific user or service account can execute within the development namespace. If you look a little more closely, it defines accessible API groups as core, extensions, and apps. And it provides access to deployments, replicaSets, and pods resources. Lastly, grant permission for resources, such as get, list, and watch. With this setting, the role called dev-team can access the deployment resource belonging to the apps API group and perform a get operation to check the information and status of the resource.

Now we need a RoleBinding to assign this created role to a specific user. The example below declares a RoleBinding with the name of dev-team-binding. And set the user to assign a specific role. The example assigns a role to a user named dev1. Finally, we gave dev1 user the dev-team role. This will allow the dev1 user to assume the roles defined in role.yaml above.

<user-role.yaml>

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: development
name: dev-team-binding
subjects:
- kind: User
name: dev1
apiGroup: ""
roleRef:
kind: Role
name: dev-team
apiGroup: ""

In addition, we will show an example of creating Roles and RoleBindings using YAML files. The example code below is the result of entering a kubectl command that creates the ‘development’ namespace and creates Role and RoleBinding inside the namespace.

$kubectl create namespace development
namespace/development created

$kubectl create -f role.yaml
role.rbac.authorization.k8s.io/dev-team created

$kubectl create -f user-role.yaml
rolebinding.rbac.authorization.k8s.io/dev-team-binding created

Kubernetes’ Role-Based Access Control allows cluster administrators to manage access to resources. This enhances security and prevents mistakes that abuse privileges. You can also segregate access rights between different users and service accounts to protect sensitive data from being viewed by unauthorized users.

3. Secrets for storing sensitive data

A Kubernetes Secret is a resource for securely storing sensitive data such as encrypted information, tokens, and passwords. In Kubernetes, secrets are commonly used to manage authentication information such as API keys, database passwords, OAuth tokens, etc. If such sensitive information is included in plain text in a Pod’s specification file or container image, it can be critical to security. So the secret information is not included in the container image, but is passed to the container via environment variables or volume mounts while running the application.

<Secrets are stored in ETCD and used as volumes and variables.>

A secret is usually defined as a base64 encoded key-value pair. Secrets are decrypted and used in the container runtime, so there is no need to implement separate decryption logic in applications that use secrets. Secrets are created independently of pods that use sensitive information. Instead, it safely stores sensitive information in a separate etcd repository, and provides it to containers when Pods need it.

Let’s create an example of a simple secret. Create and preserve a specific user’s ID and password as a secret. Suppose we have user data ‘USER_NAME=admin’, ‘PASSWORD=1f2d1e2e67df’. First, base64 encode the information as shown below.

$echo -n "admin" | base64
YWRtaW4=

$echo -n "1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm

And then, create a YAML file that creates a secret with the encoded data. The values ​​of USER_NAME and PASSWORD are base64 encoded values, but when a pod uses them, the kubelet on the worker node decodes them and provides them to the pods and containers.

apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
USER_NAME: YWRtaW4=
PASSWORD: MWYyZDFlMmU2N2Rm

The secret information created in this way is stored in the etcd database of the Kubernetes cluster control plane. etcd is the central datastore of the Kubernetes cluster, where several data are stored, including all Kubernetes resource information, configuration information, and runtime information. Secrets are stored base64 encoded in ETCD as well.

Note that Secret uses encoding and decoding rather than encryption. Thus it is not a perfect data protection method. Therefore, additional security measures are required.

For example, you can use the RBAC you learned earlier to limit access to and use of Secrets to the only authorized users. You can also use a separate encryption plugin to fully encrypt your secret data. This requires an external service such as Key Management Service (KMS).

In summary, Secrets are an important tool for securing and managing sensitive information used by applications. Secrets prevent many security vulnerabilities by protecting sensitive information within your Kubernetes cluster.

So far, we’ve covered the basic features for securing Kubernetes. Indeed, security in Kubernetes is a vast topic, but this article has introduced three of the most basic key areas. Make good use of these three security features to ensure basic Kubernetes security.

--

--

This blog is for personal study purposes, not for the company I work for. I LOVE Cloud, DevOps and Open Source.