Network policies
editNetwork policies
editNetwork policies allow you to isolate pods by restricting incoming and outgoing network connections to a trusted set of sources and destinations. This section describes how to use network policies to isolate the ECK operator and the Elastic Stack applications to a set of namespaces to implement a form of soft multi-tenancy. Soft multi-tenancy is a term used to describe a scenario where a group of trusted users (different teams within an organization, for example) share a single resource such as a Kubernetes cluster. Note that network policies alone are not sufficient for security. You should complement them with strict RBAC policies, resource quotas, node taints, and other available security mechanisms to ensure that tenants cannot access, modify, or disrupt resources belonging to each other.
There are several efforts to support multi-tenancy on Kubernetes, including the official working group for multi-tenancy and community extensions such as loft and kiosk, that can make configuration and management easier. You may still need to employ network policies such the ones described below to have fine-grained control over Elastic Stack applications deployed by your tenants.
The following sections assume that the operator is installed in the elastic-system namespace with the namespaces configuration set to team-a,team-b. Each namespace is expected to be labelled as follows:
kubectl label namespace elastic-system eck.k8s.elastic.co/operator-name=elastic-operator kubectl label namespace team-a eck.k8s.elastic.co/tenant=team-a kubectl label namespace team-b eck.k8s.elastic.co/tenant=team-b
Isolating the operator
editThe minimal set of permissions required are as follows:
Egress (outgoing) |
|
Ingress (incoming) |
|
Assuming that the Kubernetes API server IP address is 10.0.0.1, the following network policy implements the rules above.
Run kubectl cluster-info | grep master to obtain the API server IP address for your cluster.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: elastic-operator
namespace: elastic-system
spec:
egress:
- ports:
- port: 53
protocol: UDP
- ports:
- port: 443
protocol: TCP
to:
- ipBlock:
cidr: 10.0.0.1/32
- ports:
- port: 9200
protocol: TCP
to:
- namespaceSelector:
matchExpressions:
- key: eck.k8s.elastic.co/tenant
operator: In
values:
- team-a
- team-b
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
ingress:
- from:
- ipBlock:
cidr: 10.0.0.1/32
ports:
- port: 9443
protocol: TCP
podSelector:
matchLabels:
control-plane: elastic-operator
Isolating Elasticsearch
editEgress (outgoing) |
|
Ingress (incoming) |
|
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: eck-elasticsearch
namespace: team-a
spec:
egress:
- ports:
- port: 9300
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
- ports:
- port: 53
protocol: UDP
ingress:
- from:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/operator-name: elastic-operator
podSelector:
matchLabels:
control-plane: elastic-operator
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
# [Optional] Allow ingress controller pods from the ingress-nginx namespace.
#- namespaceSelector:
# matchLabels:
# name: ingress-nginx
ports:
- port: 9200
protocol: TCP
- from:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
ports:
- port: 9300
protocol: TCP
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
Isolating Kibana
editEgress (outgoing) |
|
Ingress (incoming) |
|
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: eck-kibana
namespace: team-a
spec:
egress:
- ports:
- port: 9200
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
# [Optional] Restrict to a single Elasticsearch cluster named hulk.
# elasticsearch.k8s.elastic.co/cluster-name=hulk
- ports:
- port: 53
protocol: UDP
ingress:
- from:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
# [Optional] Allow ingress controller pods from the ingress-nginx namespace.
#- namespaceSelector:
# matchLabels:
# name: ingress-nginx
ports:
- port: 5601
protocol: TCP
podSelector:
matchLabels:
common.k8s.elastic.co/type: kibana
Isolating APM Server
editEgress (outgoing) |
|
Ingress (incoming) |
|
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: eck-apm-server
namespace: team-a
spec:
egress:
- ports:
- port: 9200
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
- ports:
- port: 5601
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: kibana
- ports:
- port: 53
protocol: UDP
ingress:
- from:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
# [Optional] Allow ingress controller pods from the ingress-nginx namespace.
#- namespaceSelector:
# matchLabels:
# name: ingress-nginx
ports:
- port: 8200
protocol: TCP
podSelector:
matchLabels:
common.k8s.elastic.co/type: apm-server
Isolating Enterprise Search
editEgress (outgoing) |
|
Ingress (incoming) |
|
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: eck-enterprise-search
namespace: team-a
spec:
egress:
- ports:
- port: 9200
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
- ports:
- port: 53
protocol: UDP
ingress:
- from:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
# [Optional] Allow ingress controller pods from the ingress-nginx namespace.
#- namespaceSelector:
# matchLabels:
# name: ingress-nginx
ports:
- port: 3002
protocol: TCP
podSelector:
matchLabels:
common.k8s.elastic.co/type: enterprise-search
Isolating Beats
editSome Beats may require additional access rules than what is listed here. For example, Heartbeat will require a rule to allow access to the endpoint it is monitoring.
Egress (outgoing) |
|
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: eck-beats
namespace: team-a
spec:
egress:
- ports:
- port: 9200
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: elasticsearch
- ports:
- port: 5601
protocol: TCP
to:
- namespaceSelector:
matchLabels:
eck.k8s.elastic.co/tenant: team-a
podSelector:
matchLabels:
common.k8s.elastic.co/type: kibana
- ports:
- port: 53
protocol: UDP
podSelector:
matchLabels:
common.k8s.elastic.co/type: beat