<

Starting to Learn Kubernetes a Step Behind - 08. discovery&LB Part 1 -

Story

  1. Starting to Learn Kubernetes a Step Behind - 01. Environment Selection -
  2. Starting to Learn Kubernetes a Step Behind - 02. Docker For Mac -
  3. Starting to Learn Kubernetes a Step Behind - 03. Raspberry Pi -
  4. Starting to Learn Kubernetes a Step Behind - 04. kubectl -
  5. Starting to Learn Kubernetes a Step Behind - 05. workloads Part 1 -
  6. Starting to Learn Kubernetes a Step Behind - 06. workloads Part 2 -
  7. Starting to Learn Kubernetes a Step Behind - 07. workloads Part 3 -
  8. Starting to Learn Kubernetes a Step Behind - 08. discovery&LB Part 1 -
  9. Starting to Learn Kubernetes a Step Behind - 09. discovery&LB Part 2 -
  10. Starting to Learn Kubernetes a Step Behind - 10. config&storage Part 1 -
  11. Starting to Learn Kubernetes a Step Behind - 11. config&storage Part 2 -
  12. Starting to Learn Kubernetes a Step Behind - 12. Resource Limitations -
  13. Starting to Learn Kubernetes a Step Behind - 13. Health Checks and Container Lifecycle -
  14. Starting to Learn Kubernetes a Step Behind - 14. Scheduling -
  15. Starting to Learn Kubernetes a Step Behind - 15. Security -
  16. Starting to Learn Kubernetes a Step Behind - 16. Components -

Last time

In Starting to learn Kubernetes a step behind - 07. workloads Part 3 -, we finally finished the workloads. This time, I'm thinking of advancing discovery&LB.

discovery&LB

In Kubernetes, there are types of resources as follows. This time, we will learn about discovery&LB.

Resource ClassificationContent
Workloads ResourcesResources related to the execution of containers
Discovery&LB ResourcesResources that provide endpoints to expose containers externally
Config&Storage ResourcesResources related to configuration, secret information, persistent volumes, etc.
Cluster ResourcesResources related to security and quotas
Metadata ResourcesResources for operating resources

Kubernetes Workloads Resources (Part 1)

There are 8 types of discovery&LB.

  • Service
    • ClusterIP
    • ExternalIP
    • NodePort
    • LoadBalancer
    • Headless (None)
    • ExternalName
    • None-Selector
  • Ingress

We will learn about the overview of Service.

Kubernetes and Network

In Kubernetes, an IP address is assigned to each Pod. Therefore, when communicating between different Pods, you need the IP address of the Pod. On the other hand, you can communicate with localhost within the same Pod.

To explain, let's prepare.

# sample-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.12
          ports:
            - containerPort: 80
        - name: redis-container
          image: redis:3.2
pi@raspi001:~/tmp $ k apply -f sample-deployment.yaml
pi@raspi001:~/tmp $ k get pods -l app=sample-app -o custom-columns="NAME:{metadata.name}, IP:{status.podIP},NODE:{spec.nodeName}"
NAME                                 IP           NODE
sample-deployment-9dc487867-h7lww   10.244.1.72   raspi002
sample-deployment-9dc487867-n8x5w   10.244.2.66   raspi003
sample-deployment-9dc487867-nxbxc   10.244.2.67   raspi003
pod ip adress
pod ip adress

In such a situation, we will focus on sample-deployment-9dc487867-n8x5w:redis.

※ nginx is open on port 80.

Preparation

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# apt-get update && apt-get install curl -y
root@sample-deployment-9dc487867-n8x5w:/data# exit

Install curl because it is not installed.

Communication to the container in the same Node, same Pod

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl localhost:80
<!DOCTYPE html>
...

OK

Communication to the container in the same Node, different Pod

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.2.66:80
<!DOCTYPE html>
...
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.2.67:80
<!DOCTYPE html>
...

OK

Communication to the container in a different Node, different Pod

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.1.72:80
<!DOCTYPE html>
...

OK

Communication from MasterNode to each Pod

pi@raspi001:~/tmp $ curl 10.244.1.72:80
<!DOCTYPE html>
...
pi@raspi001:~/tmp $ curl 10.244.2.66:80
<!DOCTYPE html>
...
pi@raspi001:~/tmp $ curl 10.244.2.67:80
<!DOCTYPE html>
...

OK

As you can see from here, the network is built by Kubernetes, which includes communication within the Pod, between Pods, and even between Nodes.

Service

Service has two major functions:

  • Load balancing of traffic to pods
  • Service discovery and intra-cluster DNS

Load balancing of traffic to pods

In the previous example, it is possible to communicate between Pods. However, every time you recreate a pod, the IP address changes, so it's a bit of a hassle to create your own. That's where Service comes in. Service automatically load balances for multiple existing Pods, and also provides external IP addresses (ExternalIP) and internal IP addresses (ClusterIP).

Let's try it out.

# sample-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: sample-clusterip
spec:
  type: ClusterIP
  ports:
    - name: "http-port"
      protocol: "TCP"
      port: 8080
      targetPort: 80
  selector:
    app: sample-app

This will load balance for Pods that match app=sample-app. It listens on port 8080 from the outside and communicates with the container on port 80. Since spec.type is ClusterIP, an internal IP address is provided.

pi@raspi001:~/tmp $ k apply -f sample-clusterip.yaml
pi@raspi001:~/tmp $ k get service sample-clusterip
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
sample-clusterip   ClusterIP   10.111.197.69   <none>        8080/TCP   30s
pi@raspi001:~/tmp $ k describe service sample-clusterip
Name:              sample-clusterip
...
Selector:          app=sample-app
Type:              ClusterIP
IP:                10.111.197.69
Port:              http-port  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.72:80,10.244.2.66:80,10.244.2.67:80
...

An IP address of 10.111.197.69 has been assigned for internal use. Also, the target Pod for load balancing is the IP address of the Pod mentioned earlier. As you can see from :80 in Endpints, you can also create a service(clusterIP) for each port. (service's spec.ports is an array specification)

Let's see if we can access it. Let's change the content of index.html for each pod.

pi@raspi001:~/tmp $ for PODNAME in `k get pods -l app=sample-app -o jsonpath='{.items[*].metadata.name}'`; do
> k exec -it ${PODNAME} -- cp /etc/hostname /usr/share/nginx/html/index.html;
> done
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-nxbxc
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-n8x5w
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-h7lww

Indeed, you can access the pod with a reasonable randomness due to load balancing. Of course, you cannot access it from the outside.

Move to iMac

~ $ curl 10.111.197.69:8080
# No response

Service discovery and intra-cluster DNS

Service discovery refers to the "solution to a problem". The problem in Kubernetes is that it is difficult to identify services because services are continuously being generated dynamically. That service discovery is in Service. The following methods are available:

  • Service discovery using environment variables
    • IP address, port, and protocol are set in the Pod.
  • Service discovery using DNS A records
    • Access by domain name is possible due to the intra-cluster DNS in Kubernetes. (Follow the domain name naming rules)
  • Service discovery using DNS SRV records
    • Reverse lookup from IP address to domain name is also possible.

Unless explicitly set by dnsPolicy, records are added to the intra-cluster DNS when a Pod is created. If the intra-cluster DNS cannot resolve the name, it will query the external DNS.

Cleaning up

pi@raspi001:~/tmp $ k delete -f sample-deployment.yaml -f sample-clusterip.yaml

Finally

This time, we learned about the overview of Service. In the world of Kubernetes, the network is automatically built, so there was nothing in particular to be aware of. As we understand more, we want to know how the network is built and how the intra-cluster DNS works. Next time is here.

※ Drawing and outputting deepens understanding, so it is recommended.

If it was helpful, support me with a ☕!

Share

Related tags