Konubinix' opinionated web of thoughts

How to Organise the Inter Subchart Networkpolicies?

Fleeting

When 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:

  1. postgresql

    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
    
  2. 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
    
  3. 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:
          ...
    
  4. 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,