---
# System prepended metadata

title: Join Namespace Network Policy
tags: [' problems', ' spike', work]

---

---
tags: work, problems, spike
---
# Join Namespace Network Policy

## Problem Statement

* At the moment, we are using api to ansible tower to perform the join namespace whenever the plan requested to do so.
* Join namespace is performed in bi-directional way. That would means when we requested `namespace-a` to join `namespace-b` we called ansible tower two times, to create the following network policy (ingress) :
  * `allow-from-namespace-b` network policy in `namespace-a`
  * `allow-from-namespace-a` network policy in `namespace-b`
* This causes us massive creation of network policy that never get cleaned up on the long lived namespace.
  * For example, we have `namspace-a` that many other namespace has needs to join here, let's say `namespace-1` to `namespace-n`. This would means there will be `allow-from-namespace-1` to `allow-from-namespace-n` in `namespace-a`. 
  * When we deleted `namespace-1` to `namespace-n` the network policies that gets deleted only those under the deleted namespace, the long lived namespace would never get cleaned up its obsoleted network policy


### Additional information
* There are few default network policy created when we create namespace in the cluster
  * default-deny
  * allow-from-same-namespace
  * allow-from-global-namespace 
* We are using kubernetes network policy, its not external CRD. So everything in kubernetes example should be applicable.
  ```yaml
  kind: NetworkPolicy
  apiVersion: networking.k8s.io/v1
  metadata:
    name: default-deny
    namespace: da-saas-alfonz-test
  ```
* Below is the example of the current network policy definitions.
  ```yaml
  spec:
    podSelector: {}
    ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              name: da-saas-non-prod-c7f9b7fac9154c44a88003dba6902194
    policyTypes:
      - Ingress
  ```

* We have the following network policy by the time we created the service group via provisioning service
  * `allow-from-global-namespace` 
  ```yaml
  spec:
    podSelector: {}
    ingress:
      - from:
          - namespaceSelector:
              matchLabels:
                system-network-namespace: 'true'
    policyTypes:
      - Ingress

  ```
  * `allow-from-same-namespace`
  ```yaml
  spec:
    podSelector: {}
    ingress:
      - from:
          - podSelector: {}
    policyTypes:
      - Ingress

  ```
  * `default-deny`
  ```yaml
  spec:
    podSelector: {}
    policyTypes:
      - Ingress

  ```
## Solution & Options
* Provisioning service to have a strategy to join the namespace
  * managed by **ANSIBLE_TOWER**
    * Use existing implementation, in which the join namespace can be bidirectional/uni-directional depending on current configuration 
  * managed by **OPENSHIFT**
    * Creating new object into the namespace to apply network policy during join namespace
* We will still create 2 network policy, one is from the short lived namespace and another one in the long lived namespace
* On the creation of network policy, the main policy should be from the shorter lived namespace.   
  * Provisioning service will track the joined namespace
  * Refer to the following policy example to be autogenerated by provisioning service on the source namespace of join namespace
  ```yaml
  apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: test-network-policy
    namespace: default
  spec:
    podSelector:
      matchLabels:
        role: db
    policyTypes:
    - Ingress
    - Egress
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            name: da-saas-dev
    egress:
    - to:
      - namespaceSelector:
          matchLabels:
            name: da-saas-dev
  ```
* When the namespace get deleted, the network policy will also be deleted naturally.

## Appendix
### Example of NetworkPolicy
```yaml=
apiVersion: v1
kind: Namespace
metadata:
  name: dono-test-1
  labels:
    networking/name: dono-test-1

---

apiVersion: v1
kind: Pod
metadata:
  name: app-1
  namespace: dono-test-1
  labels:
    name: app-1
spec:
  containers:
  - name: app-1
    image: joshrosso/nginx-curl:v2
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"

---

apiVersion: v1
kind: Service
metadata:
  name: app-1
  namespace: dono-test-1
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http
    protocol: TCP
  selector:
    name: app-1
```

```yaml=
apiVersion: v1
kind: Namespace
metadata:
  name: dono-test-2
  labels:
    networking/name: dono-test-2

---
apiVersion: v1
kind: Pod
metadata:
  name: app-2
  namespace: dono-test-2
  labels:
    name: app-2
spec:
  containers:
  - name: app-2
    image: joshrosso/nginx-curl:v2
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"

---

apiVersion: v1
kind: Service
metadata:
  name: app-2
  namespace: dono-test-2
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http
    protocol: TCP
  selector:
    name: app-2

---

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-interaction-to-dono-test-1
  namespace: dono-test-2
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: dono-test-1
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: dono-test-1
```