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 MacMy 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:
As already mentioned in Matthias Ms answer there are several ways.
As the offical Kubernetes documentation specifically describes using a Service with a type NodePort I wanted to describe the workflow.
NodePort: Exposes the Service on each Node’s IP at a static port (theNodePort). AClusterIPService, to which theNodePortService routes, is automatically created. You’ll be able to contact theNodePortService, from outside the cluster, by requesting<NodeIP>:<NodePort>.If you set the
typefield toNodePort, the Kubernetes control plane allocates a port from a range specified by--service-node-port-rangeflag (default: 30000-32767). Each node proxies that port (the same port number on every Node) into your Service. Your Service reports the allocated port in its.spec.ports[*].nodePortfield.
Setup a Service with a type of NodePort
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  clusterIP: 10.0.171.239
  type: NodePortThen you can check on which port the Service is exposed to via
kubectl get svc
NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
my-service                     NodePort       10.103.218.215   <none>        9376:31040/TCP               52s
and access it via localhost using the exposed port. E.g.
curl http://localhost:31040There 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: trueDirty (the host network should not be shared for security reasons) => I did not check this solution.
2. hostPort
hostPort: 8086Does 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: apache4. 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-ingressb. 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: 80Now I can access my apache deployed with kubernetes by calling http://localhost/
Remarks for using local-dev-with-docker-for-mac-kubernetes
Further documentation
The proper way to do it is to use Ingress as explained for example in this post
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: LoadBalancerTry it now on: http://localhost:8080