K8s: How do I access my app with a service?

Viewed 1131

I'm learning K8s and installed minikube on OSX. I'm going through Nigel Poulton's K8s book and doing the lab in chapter 5 (deployments).

I have this deployment:

k8s cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deploy
spec:
  replicas: 10
  selector:
    matchLabels:
      app: hello-world
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-pod
        image: nigelpoulton/k8sbook:latest
        ports:
        - containerPort: 8080

And this service using nodeport:

k8s cat svc.yaml 
 apiVersion: v1
 kind: Service
 metadata:
    name: hello-svc
    labels:
      app: hello-world
 spec:
    type: NodePort
    ports:
    - port: 8080
      nodePort: 30001
      protocol: TCP
    selector:
      app: hello-world

The app is a simple nodejs app:

/src # cat app.js 
// Sample node.js web app for Pluralsight Docker CI course
// For demonstration purposes only
'use strict';
var express = require('express'),
app = express();
app.set('views', 'views');
app.set('view engine', 'pug');
app.get('/', function(req, res) {
res.render('home', {
});
});
app.listen(8080);
module.exports.getApp = app;

The app is running. When I access the pod I can curl it:

kubectl exec -it hello-deploy-8d494c7f6-27528 sh

/src # apk add curl
 
/src # curl localhost:8080
<html><head><title>K8s rocks!</title><link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"/></head><body><div class="container"><div class="jumbotron"><h1>Kubernetes Rocks!</h1><p>Check out my K8s Deep Dive course!</p><p> <a class="btn btn-primary" href="https://acloud.guru/learn/kubernetes-deep-dive">The video course</a></p><p></p></div></div></body></html>/src # 

But if I curl from macOS it doesn't work:

 ➜ k8s minikube ip
127.0.0.1

➜ k8s curl localhost:30001
curl: (7) Failed to connect to localhost port 30001: Connection refused

What am I missing?

EDIT: including some more output:

kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-svc    NodePort    10.98.184.143   <none>        8080:30001/TCP   6h15m
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          22h


➜  k8s minikube service list
|-------------|------------|--------------|-----|
|  NAMESPACE  |    NAME    | TARGET PORT  | URL |
|-------------|------------|--------------|-----|
| default     | hello-svc  |         8080 |     |
| default     | kubernetes | No node port |
| kube-system | kube-dns   | No node port |
|-------------|------------|--------------|-----|
➜  k8s 
1 Answers

minikube runs in a VM on your Mac so the minikube IP is not 127.0.0.1. It's actually the IP address of the VM as seen by your Mac. Now I'm not sure why you are getting 127.0.0.1 as this works fine for me:

$ minikube start
  minikube v1.11.0 on Darwin 10.15.5
✨  Using the hyperkit driver based on existing profile
  Starting control plane node minikube in cluster minikube
  Restarting existing hyperkit VM for "minikube" ...
  Preparing Kubernetes v1.18.3 on Docker 19.03.8 ...
  Verifying Kubernetes components...
  Enabled addons: dashboard, default-storageclass, storage-provisioner
  Done! kubectl is now configured to use "minikube"
$ minikube ip
192.168.64.11
$ curl 192.168.64.11:30001
<html><head><title>K8s rocks!</title><link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"/></head><body><div class="container"><div class="jumbotron"><h1>Kubernetes Rocks!</h1><p>Check out my K8s Deep Dive course!</p><p> <a class="btn btn-primary" href="https://acloud.guru/learn/kubernetes-deep-dive">The video course</a></p><p></p></div></div></body></html>

You could have a VPN software on your Mac that messes things up.

If will probably help to check the IP address that your VM has:

$ minikube ssh
                         _             _
            _         _ ( )           ( )
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)

$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 4E:33:DE:14:29:35
          inet addr:192.168.64.11  Bcast:192.168.64.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:21781 errors:0 dropped:0 overruns:0 frame:14
          TX packets:10123 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:28636337 (27.3 MiB)  TX bytes:1671406 (1.5 MiB)

Also, depending on the Hypervisor you are running (Hyperkit, VBox, etc), you might want to check a bridge is configured to talk to the VM subnet and that the bridge has an IP range that matches the IP address in the VM. For example, for Hyperkit in my case from my Mac host:

# On my mac
$ ifconfig bridge100
bridge100: flags=8a63<UP,BROADCAST,SMART,RUNNING,ALLMULTI,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether 3a:f9:d3:93:95:64
    inet 192.168.64.1 netmask 0xffffff00 broadcast 192.168.64.255
    inet6 fe80::8ad:ce3b:83d9:6c10%bridge100 prefixlen 64 secured scopeid 0x17
    inet6 fd38:a1cf:6e5c:2722:462:b0d:a2c1:69bc prefixlen 64 autoconf secured
    inet6 fd38:a1cf:6e5c:2722:983c:b72b:39e7:8b70 prefixlen 64 autoconf temporary
    Configuration:
        id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
        maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
        root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
        ipfilter disabled flags 0x0
    member: en9 flags=3<LEARNING,DISCOVER>
            ifmaxaddr 0 port 22 priority 0 path cost 0
    Address cache:
        4e:33:de:14:29:35 Vlan1 en9 1031 flags=0<>
    nd6 options=201<PERFORMNUD,DAD>
    media: autoselect
    status: active
Related