The container orchestrator war is over, and Kubernetes has won. With companies large and small rapidly adopting the platform, security has emerged as an important concern – partly because of the learning curve inherent in understanding any new infrastructure, and partly because of recently announced vulnerabilities.
Kubernetes brings another security dynamic to the table – its defaults are geared towards making it easy for users to get up and running quickly, as well as being backward compatible with earlier releases of Kubernetes that lacked important security features. Consequently, many important Kubernetes configurations are not secure by default.
One important configuration that demands attention from a security perspective is the network policies feature. Network policies specify how groups of pods are allowed to communicate with each other and other network endpoints. You can think of them as the Kubernetes equivalent of a firewall.
How to Set Up Kubernetes Ingress Networking Policies
We lay out here a step-by-step guide on how to set up network policies. The network policy spec is intricate, and it can be difficult to understand and use correctly. In this guide, we provide recommendations that significantly improve security. Users can easily implement these recommendations without needing to know the spec in detail.
A quick note: this guide focuses just on ingress network policies. When starting out, the biggest security gains come from applying ingress policies, so we recommend focusing on them first, and then adding egress policies. We discuss egress policies in detail and provide recommendations in our latest post in this series–don’t forget to check it out!
Use a network plugin that supports network policies
First things first – use a network plugin that actually enforces network policies. Although Kubernetes always supports operations on the NetworkPolicy
resource, simply creating the resource without a plugin that implements it will have no effect. Example plugins include Calico, Cilium, Kube-router, Romana and Weave Net.
“Isolate” your pods
Each network policy has a podSelector
field, which selects a group of (zero or more) pods. When a pod is selected by a network policy, the network policy is said to apply to it.
Each network policy also specifies a list of allowed (ingress and egress) connections. When the network policy is created, all the pods that it applies to are allowed to make or accept the connections listed in it. In other words, a network policy is essentially a list of allowed connections – a connection to or from a pod is allowed if it is permitted by at least one of the network policies that apply to the pod.
This tale, however, has an important twist: based on everything described so far, one would think that, if no network policies applied to a pod, then no connections to or from it would be permitted. The opposite, in fact, is true: if no network policies apply to a pod, then all network connections to and from it are permitted (unless the connection is forbidden by a network policy applied to the other peer in the connection.)
This behavior relates to the notion of “isolation”: pods are “isolated” if at least one network policy applies to them; if no policies apply, they are “non-isolated”. Network policies are not enforced on non-isolated pods. Although somewhat counter-intuitive, this behavior exists to make it easier to get a cluster up and running – a user who does not understand network policies can run their applications without having to create one.
Therefore, we recommend you start by applying a “default-deny-all” network policy. The effect of the following policy specification is to isolate all pods, which means that only connections explicitly listed by other network policies will be allowed.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
Without such a policy, it is very easy to run into a scenario where you delete a network policy, hoping to forbid the connections listed in it, but find that the result is that all connections to some pods suddenly become permitted – including ones that weren’t allowed before. Such a scenario occurs when the network policy you deleted was the only one that applied to a particular pod, which means that the deletion of the network policy caused the pod to become “non-isolated”.
Important Note: Since network policies are namespaced resources, you will need to create this policy for each namespace. You can do so by running kubectl -n <namespace> create -f <filename>
for each namespace.
Explicitly allow internet access for pods that need it
With just the default-deny-all
policy in place in every namespace, none of your pods will be able to talk to each other or receive traffic from the Internet. For most applications to work, you will need to allow some pods to receive traffic from outside sources. One convenient way to permit this setup would be to designate labels that are applied to those pods to which you want to allow access from the internet and to create network policies that target those labels. For example, the following network policy allows traffic from all (including external) sources for pods having the networking/allow-internet-access=true
label (again, as in the previous section, you will have to create this for every namespace):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: internet-access
spec:
podSelector:
matchLabels:
networking/allow-internet-access: "true"
policyTypes:
- Ingress
ingress:
- {}
For a more locked-down set of policies, you would ideally want to specify more fine-grained CIDR blocks as well as explicitly list out allowed ports and protocols. However, this policy provides a good starting point, with much greater security than the default.
Explicitly allow necessary pod-to-pod communication
After taking the above steps, you will also need to add network policies to allow pods to talk to each other. You have a few options for how to enable pod-to-pod communications, depending on your situation:
If You Don’t Know Which Pods Need To Talk To Each Other
In this case, a good starting point is to allow all pods in the same namespace to talk to each other and explicitly allow communication across namespaces, since that is usually more rare. You can use the following network policy to allow all pod-to-pod communication within a namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
If You Know The Sources and Sinks for Communication
Often, communication between pods in an application follows a hub-and-spoke paradigm, with some central pods that many other pods need to talk to. In this case, you could consider creating a label which designates pods that are allowed to talk to the “hub.” For example, if your hub is a database pod and has an app=db
label, you could allow access to the database only from pods that have a networking/allow-db-access=true
label by applying the following policy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-db-access
spec:
podSelector:
matchLabels:
app: "db"
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
networking/allow-db-access: "true"
You could do something similar if you have a server that initiates connections to many other pods. If you want to explicitly allow the pods that the server is allowed to talk to, you can set the networking/allow-server-to-access=true
label on them, and apply the following network policy (assuming your server has the label app=server
) on them:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-server-to-access
spec:
podSelector:
matchLabels:
networking/allow-server-to-access: "true"
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: "server"
If You Know Exactly Which Connections Should Be Allowed
Within the same namespace
Advanced users who know exactly which pod-to-pod connections should be allowed in their application can explicitly allow each such connection. If you want pods in deployment A to be able to talk to pods in deployment B, you can create the following policy to allow that connection, after replacing the labels with the labels of the specific deployment:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-server-to-access
spec:
podSelector:
matchLabels:
deployment-b-pod-label-1-key: deployment-b-pod-label-1-value
deployment-b-pod-label-2-key: deployment-b-pod-label-2-value
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
deployment-a-pod-label-1-key: deployment-a-pod-label-1-value
deployment-a-pod-label-2-key: deployment-a-pod-label-2-value
Across Namespaces
To allow connections across namespaces, you will need to create a label for the source namespace (unfortunately, Kubernetes does not have any labels on namespaces by default) and add a namespaceSelector
query next to the podSelector
query. To label a namespace, you can simply run the command: kubectl label namespace <name> networking/namespace=<name>
With this namespace label in place, you can allow deployment A in namespace N1 to talk to deployment B in namespace N2 by applying the following network policy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-n1-a-to-n2-b
namespace: N2
spec:
podSelector:
matchLabels:
deployment-b-pod-label-1-key: deployment-b-pod-label-1-value
deployment-b-pod-label-2-key: deployment-b-pod-label-2-value
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
networking/namespace: N1
podSelector:
matchLabels:
deployment-a-pod-label-1-key: deployment-a-pod-label-1-value
deployment-a-pod-label-2-key: deployment-a-pod-label-2-value
What About New Deployments?
Although explicitly allowing connections in this manner is great for security, this approach does affect usability. When you create new deployments, they will not be able to talk to anything by default until you apply a network policy. To mitigate this potentially frustrating user experience, you could create the following pair of network policies, which allow pods labeled networking/allow-all-connections=true
to talk to all other pods in the same namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-from-new
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
networking/allow-all-connections: "true"
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-new
spec:
podSelector:
matchLabels:
networking/allow-all-connections: "true"
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {}
You can then apply the networking/allow-all-connections=true
label to all newly created deployments, so that your application works until you create specially crafted network policies for them, at which point you can remove the label.
Summary
While these recommendations provide a good starting point, network policies are a lot more involved. If you’re interested in exploring them in more detail, be sure to check out the Kubernetes tutorial as well as some handy network policy recipes.
In a future post in this series, we will release an accompanying open-source tool that allows you to easily apply the recommendations in this article as well as some other best practices.
Here at StackRox, we’ve spent a lot of time thinking about how to operationalize network policies. The StackRox Kubernetes Security Platform automatically suggests and can generate network policies that enable just those communications paths your applications need. You can learn more about these capabilities in our network policy enforcement discussion.
Note: All the example YAMLs in this article can be downloaded at https://github.com/stackrox/network-policy-examples
저자 소개
유사한 검색 결과
채널별 검색
오토메이션
기술, 팀, 인프라를 위한 IT 자동화 최신 동향
인공지능
고객이 어디서나 AI 워크로드를 실행할 수 있도록 지원하는 플랫폼 업데이트
오픈 하이브리드 클라우드
하이브리드 클라우드로 더욱 유연한 미래를 구축하는 방법을 알아보세요
보안
환경과 기술 전반에 걸쳐 리스크를 감소하는 방법에 대한 최신 정보
엣지 컴퓨팅
엣지에서의 운영을 단순화하는 플랫폼 업데이트
인프라
세계적으로 인정받은 기업용 Linux 플랫폼에 대한 최신 정보
애플리케이션
복잡한 애플리케이션에 대한 솔루션 더 보기
오리지널 쇼
엔터프라이즈 기술 분야의 제작자와 리더가 전하는 흥미로운 스토리
제품
- Red Hat Enterprise Linux
- Red Hat OpenShift Enterprise
- Red Hat Ansible Automation Platform
- 클라우드 서비스
- 모든 제품 보기
툴
체험, 구매 & 영업
커뮤니케이션
Red Hat 소개
Red Hat은 Linux, 클라우드, 컨테이너, 쿠버네티스 등을 포함한 글로벌 엔터프라이즈 오픈소스 솔루션 공급업체입니다. Red Hat은 코어 데이터센터에서 네트워크 엣지에 이르기까지 다양한 플랫폼과 환경에서 기업의 업무 편의성을 높여 주는 강화된 기능의 솔루션을 제공합니다.