This is an example of how to access a service running in a different namespace on the same cluster, without needing to leave the cluster and reenter through the ingress. This helps to remove a layer of networking from the communication and is considered a best practice.
kubectl create namespace testns
namespace/testns created
kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "sleep 3600"
pod/busybox created
kubectl run busybox --namespace testns --image=busybox --restart=Never -- /bin/sh -c "sleep 3600"
pod/busybox created
run mysql --image=mysql --restart=Never --env=MYSQL_ROOT_PASSWORD=password123 --labels=app=mysql
pod/mysql created
vim mysqlsvc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: default
spec:
clusterIP: None
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mysql
type: ClusterIP
kubectl create -f mysqlsvc.yaml
service/mysql created
You should now have a mysql database running with a service called mysql. Let's validate we can connect to it from the busybox pod in the default namespace (both pods in the same namespace)
kubectl exec -it busybox -- /bin/sh -c "ping -c1 mysql"
PING mysql (172.17.0.7): 56 data bytes
64 bytes from 172.17.0.7: seq=0 ttl=64 time=0.065 ms
--- mysql ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.065/0.065/0.065 ms
It works. We can see the mysql pod from the busybox pod in the default namespace.
kubectl exec -it busybox --namespace testns -- /bin/sh -c "ping -c1 mysql"
ping: bad address 'mysql'
command terminated with exit code 1
This fails because the mysql service isn't known in the testns. The mysql service is avaiale at mysql.default.svc.cluster.local. But, before we can connect to it, we need to make it visible in the testns namespace.
vim mysql-ext-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: mysql
namespace: testns
spec:
type: ExternalName
externalName: mysql.default.svc.cluster.local
ports:
- port: 3306
kubectl create -f mysql-ext-svc.yaml
service/mysql created
kubectl exec -it busybox --namespace testns -- /bin/sh -c "ping -c1 mysql"
PING mysql (172.17.0.7): 56 data bytes
64 bytes from 172.17.0.7: seq=0 ttl=64 time=0.056 ms
--- mysql ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.056/0.056/0.056 ms
If you have a denyall network policy implemented in your cluster, you will also need to implement the following to allow traffic to and from the busybox pods/namespaces...
Create ingres_ns.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: default.allow-ingress-from-client-to-server
namespace: default
spec:
order: 1000 # must be set (lower values take precedence)
selector: app == 'mysql' # apply policy on pod(s) with matching label
types:
- Ingress
ingress:
- action: Allow
protocol: TCP
source:
namespaceSelector: namespace == 'testns' # allow ingress from pod(s) in specific namespace
selector: run == 'busybox' # allow ingress from pod(s) with matching label
destination:
selector: app == 'mysql' # allow ingress to pod(s) with matching label
ports: # must define port(s) on destination
- 3306 # allow egress to port 3306
Create the network Ingress Policy in the default namespace
kubectl create -f ingress-ns.yaml
Create egress-ns.yaml file.
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: default.allow-egress-from-busybox-to-mysql
namespace: testns
spec:
order: 1000 # must be set (lower values take precedence)
selector: run == 'busybox' # apply policy on pod(s) with matching label
types:
- Egress
egress:
- action: Allow
protocol: TCP
source:
selector: run == 'busybox' # allow egress from pod(s) with matching label
destination:
namespaceSelector: namespace == 'default' # allow egress from pod(s) in specific namespace
selector: app == 'mysql' # allow egress to pod(s) with matching label
ports: # must define port(s) on destination
- 3306 # allow egress to port 3306
Create Egress network policy in the testns namespace
kubectl create -f egress-ns.yaml