본문 바로가기

k8s 실전 프로젝트/2. Application 빌드와 배포

Deployment, Service, Ingress 흐름 설명

# 생성 파일 (drawio, png)

Deployment, Service, Ingress Port 설명.drawio
0.00MB
Deployment, Service, Ingress Port 설명.png
1.39MB

# Deployment, Service, Ingress 서비스 흐름 구조도

# 흐름 설명

1. User가 ALB의 DNS:80 주소로 접근을 한다.

EKS에서 ALB 서비스를 생성을 하면 자동으로 ALB가 생성이 되고, 생성된 ALB의 DNS주소가 최종 User가 접근하는 접속 주소가 된다.

EKS에서 ingress를 조회하면 아래와 같이 현재 생성된 ingress 서비스 정보를 확인할 수 있다.

kubectl get ingress
NAME            CLASS    HOSTS   ADDRESS                                                                       PORTS   AGE
nginx-ingress   <none>   *       k8s-default-nginxing-12345678-12345678.ap-northeast-2.elb.amazonaws.com   80      42h

위에서 PORTS 부분을 보면 80으로 설정되어 있는 것을 확인할 수 있는데, 해당 서비스를 조금 더 자세히 들여다보면 아래와 같다.

정보를 확인하면 Address는 ALB의 DNS 주소가 될 것이다.

Rules를 확인하면 Host : * (모든 호스트를 나타낸다), Path : / (root 패스를 가리킨다), Backends : nginx-service:8080 (모든 트래픽을 해당 경로로 던져라라는 뜻이다. (192.168.133.128:80,192.168.142.68:80,192.168.172.109:80 + 5 more...) 내용을 보면 경로로 전달되는 모든 트래픽을 5개의 pod IP로 분산하여 전달하는 과정을 볼 수 있다.)

* 여기서 의문을 가질수 있는 게 바로 Dafault backend일 것이다. Dafault backend의 정보는 아래 더보기를 클릭하여 접힌글을 참조하면 된다. (발 번역이니 번역은 알아서...)

더보기
디폴드 백엔드는 잉그레스 리소스에서 알지 못하는 요청이나 
맵핑되지 않은 정보를 핸들링하기 위해서 사용된다.
The default backend is used for handling an unknown request or 
a request that is not mapped to any path or host in the ingress resource. 
만약 서비스에 대한 정의나 맵핑을 하지 않았을 경우 디폴드 백엔드는 HTTP 404를
리턴한다. 이런 이슈를 해결하기 위해서는 서비스나 맵을 디폴트 백엔드로
생성하면 해결이 된다.
If you don't define this service and enter a path not mapped, 
it returns an HTTP 404 (page not found) error. To fix this issue, 
create a service and map it to the default backend.
kubectl describe ingress nginx-ingress
Name:             nginx-ingress
Namespace:        default
Address:          k8s-default-nginxing-12345678-12345678.ap-northeast-2.elb.amazonaws.com
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host  Path  Backends
  ----  ----  --------
  *
        /   nginx-service:8080 (192.168.133.128:80,192.168.142.68:80,192.168.172.109:80 + 5 more...)

2. Service 설명

ALB에서 80으로 던진 트래픽을 Ingress에서 8080의 pod로 라우팅을 하고, Service의 8080으로 전달을 한다.

여기서부터 서비스의 내용을 보면 서비스는 8080으로 받은 트래픽을 프로그램 포트인 targetPort 80으로 전달하고, 해당 targetPort가 바라보는 Container의 포트인 80으로 트래픽을 전달 후 컨테이너로 전달하는 구조이다.

글로 쓰면 조금 감히 잡히지 않는 부분이 있으니 실제 코드를 보고 파악해 보자.

생성된 서비스 중 nginx-service에 대한 정보를 확인한다.

아래 내용중 Port : 8080/TCP (해당 서비스의 포트는 8080이라는 의미), TargetPort : 80 (pod의 port를 나타냄), Endpoints : 192.168..... (해당 pod의 Endpoints IP 정보라고 보면 된다. 여기서는 pod가 5개를 생성하였기 때문에 5개의 IP가 부여된 것을 볼 수 있다.)

 

kubectl describe service nginx-service
Name:                     nginx-service
Namespace:                default
Labels:                   <none>
Annotations:              alb.ingress.kubernetes.io/healthcheck-path: /healthy
                          kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"alb.ingress.kubernetes.io/healthcheck-path":"/healthy"},"name":"nginx-serv...
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.100.118.105
Port:                     <unset>  8080/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  31547/TCP
Endpoints:                192.168.133.128:80,192.168.142.68:80,192.168.172.109:80 + 5 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

위의 내용을 요약해보면 해당 서비스의 포트는 8080이고, 8080으로 들어온 트래픽을 80의 pod에게 전달하는 구조라고 볼 수 있다.

다음으로 Deployment에 대해서 알아본다.

3. Deployment 설명

주요 내용 위주로 Pod Template 부분을 확인해 보면, Containers : 내용에 해당 이미지와 해당 이미지가 사용하는 Port를 확인할 수 있다. 이미지를 docker container에서 받았으므로, 간단하게 말해서 Docker 컨테이너가 사용할 포트라고 보면 된다.

kubectl describe deployment nginx
...
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.14.2
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
...

4. 서비스 흐름

반복적 이지만, 서비스의 흐름에 대해서 다시 보자.

1. Deployment 정의 : Deployment는 메타데이터 및 pod 리플리카 개수, 컨테이너 이미지, 이미지 포트 등을 정의한다.

더보기
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 8
  selector:
    matchLabels:
      app: nginx 
  template:
    metadata:
      labels:
        app: nginx 
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

2. Service 정의 : Service는 아래와 같이 어노테이션 및 서비스 포트 및 타깃 포트 등을 정의한다.

더보기
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: "/healthy"
spec:
  selector:
     app: nginx
  type: NodePort
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80

3. ingress 정의 : 어노테이션 및 ingress의 서비스 name과 port를 정의한다.

더보기
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: "nginx-service"
                port:
                  number: 8080

# Deployment와 Service 그리고 Ingress의 관계가 간단하게 정리된 그림 (예시)

# 위의 예시를 토대로 Deployment와 Service 그리고 Ingress의 관계를 Flow로 표현한 그림

* 추가로 pod의 정보를 확인해 보자.

kubectl get pod를 통해 pod의 정보를 확인한다. 최초 생성 시 pod 숫자를 8개로 지정했으므로 8개의 pod가 생성된 것을 확인할 수 있다.

kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-66b6c48dd5-4jh8n   1/1     Running   0          45h
nginx-66b6c48dd5-4qttm   1/1     Running   0          45h
nginx-66b6c48dd5-4wwz9   1/1     Running   0          43h
nginx-66b6c48dd5-cpdv9   1/1     Running   0          43h
nginx-66b6c48dd5-cr276   1/1     Running   0          45h
nginx-66b6c48dd5-h9bmc   1/1     Running   0          45h
nginx-66b6c48dd5-ljg95   1/1     Running   0          43h
nginx-66b6c48dd5-wv5p9   1/1     Running   0          45h

kubectl describe pod <pod_name> 을 통해 pod의 자세한 정보를 확인한다.

중간 부분 Containers : 를 확인하면 Container ID, Image 명, Image ID, Port 정보 등 여러 서비스 정보를 확인할 수 있다.

Labels, Namespace, Tolerations 등의 옵션도 중요 하므로 거의 모든 옵션 설명을 한 번씩 정리하는 것이 좋다.

kubectl describe pod nginx-66b6c48dd5-4jh8n
Name:         nginx-66b6c48dd5-4jh8n
Namespace:    default
Priority:     0
Node:         ip-192-168-109-228.ap-northeast-2.compute.internal/192.168.109.228
Start Time:   Tue, 08 Mar 2022 06:13:05 +0000
Labels:       app=nginx
              pod-template-hash=66b6c48dd5
Annotations:  kubernetes.io/psp: eks.privileged
Status:       Running
IP:           192.168.79.148
IPs:
  IP:           192.168.79.148
Controlled By:  ReplicaSet/nginx-66b6c48dd5
Containers:
  nginx:
    Container ID:   docker://bfe0ecbd6837956fcc441b51ceb67491e9c0cefaa0fa66e723c94ffdf29a0d0c
    Image:          nginx:1.14.2
    Image ID:       docker-pullable://nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Tue, 08 Mar 2022 06:13:14 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rjd55 (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-rjd55:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute for 300s
                             node.kubernetes.io/unreachable:NoExecute for 300s
Events:                      <none>

대략적인 k8s의 서비스 흐름에 대해서 알아보았다. 아직 많은 개념의 이해가 부족하고 다양한 환경에서 다양한 서비스를 실제 구현을 해봐야 조금 더 감이 잡힐 것 같다.

 

# 참고 사이트

https://dwdraju.medium.com/how-deployment-service-ingress-are-related-in-their-manifest-a2e553cf0ffb

 

How Deployment, Service & Ingress are Related in their Manifest?

While getting started to write yaml manifest of various Kubernetes resources, we get confused on label, selector, name etc. Let’s go…

dwdraju.medium.com

- 끝 -