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