Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expose service on local kubernetes

Tags:

kubernetes

I'm running a local kubernetes bundled with docker on Mac OS.

How can I expose a service, so that I can access the service via a browser on my Mac?

I've created:

a) deployment including apache httpd.

b) service via yaml:

apiVersion: v1
kind: Service
metadata:
  name: apaches
spec:
  selector:
    app: web
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
  externalIPs:
  - 192.168.1.10 # Network IP of my Mac

My service looks like:

$ kubectl get service apaches
NAME      TYPE       CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
apaches   NodePort   10.102.106.158   192.168.1.10   80:31137/TCP   14m

I can locally access the service in my kubernetes cluster by wget $CLUSTER-IP

I tried to call http://192.168.1.10/ on my Mac, but it doesn't work.

This question deals to a similar issue. But the solution does not help, because I do not know which IP I can use.

Update

Thanks to Michael Hausenblas I worked out a solution using Ingress. Nevertheless there are still some open questions:

  • What is the meaning of a service's externalIP? Why do I need an externalIP when I do not directly access a service from external?
  • What is the meaning of the service port 31137?
    • The kubernetes docs describe a method to [publish a service in minikube via NodePort][4]. Is this also possible with kubernetes bundled on docker?
like image 687
Matthias M Avatar asked Mar 11 '18 10:03

Matthias M


People also ask

How do you expose existing services in Kubernetes?

From the Service type drop-down list, select Cluster IP. Click Expose. When your Service is ready, the Service details page opens, and you can see details about your Service. Under Cluster IP, make a note of the IP address that Kubernetes assigned to your Service.

How do I access Clusterber services in Kubernetes from outside?

To reach the ClusterIp from an external computer, you can open a Kubernetes proxy between the external computer and the cluster. You can use kubectl to create such a proxy. When the proxy is up, you're directly connected to the cluster, and you can use the internal IP (ClusterIp) for that Service .


3 Answers

There are several solutions to expose services in kubernetes: http://alesnosek.com/blog/2017/02/14/accessing-kubernetes-pods-from-outside-of-the-cluster/

Here are my solutions according to alesnosek for a local kubernetes bundled with docker:

1. hostNetwork

hostNetwork: true

Dirty (the host network should not be shared for security reasons) => I did not check this solution.

2. hostPort

hostPort: 8086

Does not apply to services => I did not check this solution.

3. NodePort

Expose the service by defining a nodePort:

apiVersion: v1
kind: Service
metadata:
  name: apaches
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30000
  selector:
    app: apache

4. LoadBalancer

EDIT @MathObsessed posted the solution in his anwer.

5. Ingress

a. Install Ingress Controller

git clone https://github.com/jnewland/local-dev-with-docker-for-mac-kubernetes.git

kubectl apply -f nginx-ingress/namespaces/nginx-ingress.yaml -Rf nginx-ingress

b. Configure Ingress

kubectl apply -f apache-ing.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apache-ingress
spec:
  rules:
  - host: localhost
    http:
      paths:
      - path: /
        backend:
          serviceName: apaches
          servicePort: 80

Now I can access my apache deployed with kubernetes by calling http://localhost/

Remarks for using local-dev-with-docker-for-mac-kubernetes

  • The repo simplifies the deployment of the offical ingress-nginx controller
  • For production use I would follow the official guide.
  • The repos ships with a tiny full featured ingress example. Very useful for getting quickly a working example application.

Further documentation

  • https://kubernetes.io/docs/concepts/services-networking/ingress
like image 182
Matthias M Avatar answered Sep 19 '22 10:09

Matthias M


For those still looking for an answer. I've managed to achieve this by adding another Kube service just to expose my app to localhost calls (via browser or Postman):

kind: Service
apiVersion: v1
metadata:
  name: apaches-published
spec:
  ports:
    - name: http
      port: 8080
      targetPort: 80
      protocol: TCP
  selector:
    app: web
  type: LoadBalancer

Try it now on: http://localhost:8080

like image 13
MathObsessed Avatar answered Sep 19 '22 10:09

MathObsessed


Really simple example

METHOD1

$ kubectl create deployment nginx-dep --image=nginx --replicas=2
  • Get the pods
$ kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
nginx-dep-5c5477cb4-76t9q   1/1     Running   0          7h5m
nginx-dep-5c5477cb4-9g84j   1/1     Running   0          7h5m
  • Access the pod using kubectl port
$ kubectl port-forward nginx-dep-5c5477cb4-9g84j 8888:80
Forwarding from 127.0.0.1:8888 -> 80
Forwarding from [::1]:8888 -> 80
  • Now do a curl to the localhost:8888
$ curl -v http://localhost:8888 

METHOD2

You can expose port 80 of the deployment (where the application is runnin i.e. nginx port) via a NodePort

$ kubectl expose deployment nginx-dep --name=nginx-dep-svc --type=NodePort --port=80
  • Get the service
$ kubectl get svc 
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1      <none>        443/TCP        31d
nginx-dep-svc   NodePort    10.110.80.21   <none>        80:31239/TCP   21m
  • Access the deployment using hte NodePort
$ curl http://localhost:31239  
like image 2
codeaprendiz Avatar answered Sep 23 '22 10:09

codeaprendiz