13

I have a bare-metal kubernetes (v1.11.0) cluster created with kubeadm and working fine without any issues. Network with calico and made it a single node cluster using kubectl taint nodes command. (single node is a requirement).

I need to run mydockerhub/sampleweb static website image on host port 80. Assume the IP address of the ubuntu server running this kubernetes is 192.168.8.10.

How to make my static website available on 192.168.8.10:80 or a hostname mapped to it on local DNS server? (Example: frontend.sampleweb.local:80). Later I need to run other services on different port mapped to another subdomain. (Example: backend.sampleweb.local:80 which routes to a service run on port 8080).

I need to know:

  1. Can I achieve this without a load balancer?

  2. What resources needed to create? (ingress, deployment, etc)

  3. What additional configurations needed on the cluster? (network policy, etc)

    Much appreciated if sample yaml files are provided.

I'm new to kubernetes world. I got sample kubernetes deployments (like sock-shop) working end-to-end without any issues. I tried NodePort to access the service but instead of running it on a different port I need to run it exact port 80 on the host. I tried many ingress solutions but didn't work.

Screenshot of my setup:
enter image description here

Community
  • 1
  • 1
sithumc
  • 3,254
  • 8
  • 27
  • 46
  • your task is solved by `docker run ...`, while your "later task" is solved by `docker-compose`. Why do you need Kubernetes? – Konstantin Vustin Jul 17 '18 at 04:11
  • Appreciate your suggestion. This is the start and will be developed further in micro-service architecture. Currently testing the app on-premise ubuntu server and will be deployed in the cloud soon. Autoscaling, load balancing will be used later. – sithumc Jul 17 '18 at 05:32

2 Answers2

11

I recently used traefik.io to configure a project with similar requirements to yours.

So I'll show a basic solution with traefik and ingresses.

I dedicated a whole namespace (you can use kube-system), called traefik, and created a kubernetes serviceAccount:

apiVersion: v1
kind: Namespace
metadata:
  name: traefik
---
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: traefik
  name: traefik-ingress-controller

The traefik controller which is invoked by ingress rules requires a ClusterRole and its binding:

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
  namespace: traefik
  name: traefik-ingress-controller

The traefin controller will be deployed as daemonset (i.e. by definition one for each node in your cluster) and a Kubernetes service is dedicated to the controller:

kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: traefik
  labels:
    k8s-app: traefik-ingress-lb
spec:
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      containers:
      - name: traefik-ingress-lb
        image: traefik
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: admin
          containerPort: 8080
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --api
        - --kubernetes
        - --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
  namespace: traefik
  name: traefik-ingress-service
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: web
    - protocol: TCP
      port: 8080
      name: admin

The final part requires you to create a service for each microservice in you project, here an example:

apiVersion: v1
kind: Service
metadata:
  namespace: traefik
  name: my-svc-1
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
  - port: 80 
    targetPort: 8080

and also the ingress (set of rules) that will forward the request to the proper service:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: traefik
  name: ingress-ms-1
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: my-address-url
    http:
      paths:
      - backend:
          serviceName: my-svc-1
          servicePort: 80

In this ingress I wrote a host URL, this will be the entry point in your cluster, so you need to resolve the name to your master K8S node. If you have more nodes which could be master, then a loadbalancer is suggested (in this case the host URL will be the LB).

Take a look to kubernetes.io documentation to have clear the concepts for kubernetes. Also traefik.io is useful.

I hope this helps you.

Nicola Ben
  • 10,615
  • 8
  • 41
  • 65
  • 1
    Can you provide the remaining yml which I can run `image: mydockerhub/sampleweb:latest`. So this answer will be complete. – sithumc Aug 21 '18 at 11:02
  • It doesn't matter the yml in which you deploy your application, it's the service mananing your app that is important. And to that service you refer in your ingress. I described it in the last two code snippets (svc+ing) – Nicola Ben Aug 21 '18 at 12:12
  • Is it necessary to run my service/deployment in the same `traefik` namespace where the ingress runs? – sithumc Aug 21 '18 at 12:20
  • No, I put the ingress in the same namespace of your service. – Nicola Ben Aug 21 '18 at 12:22
  • I have a EKS and traefik ingress controler and I got a 404 when I trying to get dashboard page. the host value is `xxx.elb.amazonaws.com` – framled Nov 24 '18 at 18:48
  • I've tried this solution. However, whenever I enable the service and ingress for my app, all worker nodes become NotReady. The kubelet logs on the worker nodes show a lot of errors like: updating node status, will retry: error getting node "k8s-worker1": Get https://localhost:6443/api/v1/nodes/k8s-worker1?resourceVersion=0&timeout=10s: unexpected EOF – senorsmile Jan 24 '19 at 23:10
2

In addition to the andswer of Nicola Ben , You have to define an externalIPs in your traefik service, just follow the steps of Nicola Ben and add a externalIPs section to the service "my-svc-1" .

apiVersion: v1
kind: Service
metadata:
  namespace: traefik
  name: my-svc-1
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
  - port: 80 
    targetPort: 8080
  externalIPs:
  - <IP_OF_A_NODE>

And you can define more than on externalIP.

mmbenyoub
  • 54
  • 1
  • 4