How to Organise the Inter Subchart Networkpolicies?
FleetingWhen playing with k8s and in particular helm, you quickly have a bunch of entangled configurations. Each chart providing an ad-hoc mean to describe the resources.
One of the great feature of helm chart is the possibility to pick subcharts and assemble them. But assembling parts in general assume some kind of standard and there does not seem to exist one when network policies are involved.
Here, I’m focused on inter subchart network policies. In general, I don’t have any issue with the definition of the ones that are involved in between components of the subchart. I am assembling subcharts and need some glue to get them working as a coherent ensemble, this glue is the inter subcharts network policies.
Let’s imagine a stack in which you want to install:
-
Using a bitnami posgresql, you get those values to customize.
my-db: primary: networkPolicy: ingressNSMatchLabels: kubernetes.io/metadata.name: somens ingressNSPodMatchLabels: app.kubernetes.io/name: somedeployment
-
hashicorp vault whose chart decided to be more low level. You then have to specify
networkPolicy: enabled: true ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: somens podSelector: matchLabels: app.kubernetes.io/name: somedeployment
-
mysql. In that case you can provide the network policy by simply adding a label into the clients and write something like
apiVersion: apps/v1 kind: Deployment metadata: name: somename ... spec: ... template: metadata: labels: mysql-client: true spec: ...
-
another dependency (mongodb?) that did not specify network policies in its templates. In that case, you have to create the resources yourself, something like.
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: somepart-to-someotherpart namespace: default spec: podSelector: matchLabels: app: thepartacceptingconnections policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: somens podSelector: matchLabels: app.kubernetes.io/name: thepartissuingtheconnection ports: - protocol: TCP port: 9000 - protocol: TCP port: 8080
In case I needs to connect components that I created myself, I will also have to specify network policies. I might be tempted to follow any of those conventions or invent mine.
In the end, it becomes very hard, by simply looking at the code, to find out how the networkpolicy are organized, because you have to enter into each specific implementation.
I like the “X-client: true” pattern, as it puts the whole logic in the subchart. If at some point I don’t need the client, I can simply remove it and the associated values and that’s all.
But it relies on the service to implement the X-client pattern and on the client to implement a way to specify labels. So I cannot choose to follow this pattern everywhere.
On the other hand, I can decide to provide ALL the inter subchart networkpolicies and not rely on their specific definitions. It makes sense, as I assemble parts together. Networkpolicies are a kinda glue to make them fit together in a coherent ensemble, so I might as well want to explicitly describe that glue.
I’m faced with a dilemma: should I use the pattern that I find elegant but loose uniformity or the other way around? After all, both elegance and uniformity contribute to the readability of the code, and readability counts.
It may be noted that even if less elegant, providing the inter subchart networkpolicies can be made very simple thanks to go template. In the end, it would simply look like a list of namespace-src/name-src:port-src -> namespace-dst/name-dst:port-dst.
I eventually decided that it was not worth using the elegant but specific methods and use the following rules:
- write the networkpolicies myself and make them available in the values.yaml,
- only specify them in terms of ingress rules, each policy indicating what pod accepts connections from what pods,