Kubernetes : Service/Ingress

Sixhustle·2020년 10월 10일
0

Kubernetes 시작하기

목록 보기
3/3
post-custom-banner

Kubernetes cluster 안에서 아래의 리소스를 이용해서 내/외부에서 호출할 수 있습니다.

Service

Kubernetes안에서 Replicaset에 대한 경로Client가 하나의 이름으로 접근할 수 있도록 하는 Service discovery를 제공하는 리소스 입니다.

아래는 release속성값으로 spring과 summer를 추가한 ReplicaSet Manifest파일입니다.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: echo-spring
  labels:
    app: echo
    release: spring
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
      release: spring
  template:
    metadata:
      labels:
        app: echo
        release: spring
    spec:
      containers:
      - name: nginx
        image: gihyodocker/nginx:latest
        env:
        - name: BACKEND_HOST
          value: localhost:8080
        ports:
        - containerPort: 80
      - name: echo
        image: gihyodocker/echo:patched
        ports:
        - containerPort: 8080
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: echo-summer
  labels:
    app: echo
    release: summer
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo
      release: summer
  template:
    metadata:
      labels:
        app: echo
        release: summer
    spec:
      containers:
      - name: nginx
        image: gihyodocker/nginx:latest
        env:
        - name: BACKEND_HOST
          value: localhost:8080
        ports:
        - containerPort: 80
      - name: echo
        image: gihyodocker/echo:patched
        ports:
        - containerPort: 8080
$ kubectl apply -f simple-replicaset-with-label.yaml
replicaset.apps/echo-spring created
replicaset.apps/echo-summer created

$ kubectl get pod -l app=echo -l release=spring
NAME                READY   STATUS    RESTARTS   AGE
echo-spring-dvs8k   2/2     Running   0          2m57s

$ kubectl get pod -l app-echo -l release=summer
NAME                READY   STATUS    RESTARTS   AGE
echo-summer-kp8b7   2/2     Running   0          3m14s
echo-summer-q6bgb   2/2     Running   0          3m14s

위 manifest파일에서 설정한 replicas숫자대로 release=spring은 1개, release=summer는 2개의 Pod가 생성된 것을 확인할 수 있습니다.


apiVersion: v1
kind: Service
metadata:
  name: echo
spec:
  selector:
    app: echo
    release: summer
  ports:
    - name: http
      port: 80

위는 app=echo & release=summer인 Pod만 접근할 수 있는 서비스 manifest파일입니다.
그림처럼 app=echo & release=spring Pod에는 접근할 수 없습니다.


$ kubectl apply -f simple-service.yaml
service/echo created

$ kubectl get service echo
NAME   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
echo   ClusterIP   10.104.121.79   <none>        80/TCP    16s

Service는 Kubernetes cluster안에서만 접근할 수 있습니다. 따라서, debugging용 임시 container를 배포하고, curl명령으로 release=summer pod에만 트래픽이 전달되는지 확인해보겠습니다.

$ kubectl run -i --rm --tty debug --image=gihyodocker/fundamental:0.1.0 --restart=Never -- bash -il

$ debug:/# curl http://echo/
Hello DOcker!!

$ kubectl get pod
NAME                READY   STATUS    RESTARTS   AGE
debug               1/1     Running   0          76s
echo-spring-dvs8k   2/2     Running   0          16m
echo-summer-kp8b7   2/2     Running   0          16m
echo-summer-q6bgb   2/2     Running   0          16m

$ kubectl logs -f echo-summer-q6bgb -c echo
2020/10/10 04:38:52 start server
2020/10/10 04:38:52 image changed
2020/10/10 04:55:19 received request

$ kubectl logs -f echo-spring-dvs8k -c echo
2020/10/10 04:38:22 start server
2020/10/10 04:38:22 image changed

http://echo/로 호출 후, release=summer Pod를 보면 received request로그를 통해 트래픽이 전달된 것을 확인할 수 있습니다.
http호출시, 2개의 release=summer Pod에 랜덤으로 트래픽이 전달됩니다.
반면, release=spring Pod에는 트래픽이 없는 것을 확인할 수 있습니다.

ClusterIP 서비스

ClusterIP는 서비스의 여러 type 중 하나로, default 값입니다.
ClusterIP는 Kubernetes Cluster의 내부 IP 주소에 Service를 공개할 수 있습니다.
따라서 Pod간 접근할 때 서비스를 거쳐가도록 할 수 있습니다. 다만, 외부에서 접근할 수 없습니다.

NodePort

Cluster 외부에서 접근할 수 있는 서비스입니다.
각 노드에서 서비스 포트로 접속하기 위한 Global port를 개방하는 점이 ClusterIP와 차이점입니다.

apiVersion: v1
kind: Service
metadata:
  name: echo
spec:
  type: NodePort
  selector:
    app: echo
  ports:
    - name: http
      port: 80
$ kubectl apply -f simple-service-nodeport.yaml
service/echo configured

$ kubectl get svc echo
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
echo   NodePort   10.104.121.79   <none>        80:31787/TCP   23m

$ curl http://127.0.0.1:31787
Hello Docker!!%

NodePorty type으로 새로운 Service를 만들어 apply해줍니다.
svc port정보를 보면, 80:31787/TCP라고 명시되어 있습니다. Node의 31787 port로 서비스에 접근할 수 있다는 내용입니다.
이렇게 Service를 Kubernetes Cluster 외부로 공개할 수 있습니다.

LoadBalancer 서비스

Local Kubernetes환경에서는 사용할 수 없는 서비스입니다.
GCP(Cloud Load Balancing), AWS(Elastic Load Balancing)와 같은 클라우드 플랫폼에서 제공하는 LoadBalancer와 연동하기 위해 사용됩니다.


Ingress

Kubernetes cluster 외부로 Service를 노출시키긴 위해서 NodePort를 사용할 수 있습니다.
이 방법은 L4 Level까지만 다룰 수 있고, HTTP/HTTPS처럼 경로 기반으로 서비스를 전환하는 L7 레벨의 제어는 불가능 합니다.

이를 해결하기 위한 리소스가 Ingress입니다.
Service를 이용한 Kubernetes cluster를 외부에 노출할 수 있고, 가상 호스트 및 경로 기반의 HTTP Routing을 양립시킬 수 있습니다.

$ kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/mandatory.yaml


$ kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.16.2/deploy/provider/cloud-generic.yaml

$ kubectl -n ingress-nginx get service,pod
NAME                           TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/default-http-backend   ClusterIP      10.103.51.46     <none>        80/TCP                       133m
service/ingress-nginx          LoadBalancer   10.107.202.110   localhost     80:32287/TCP,443:31337/TCP   132m

NAME                                           READY   STATUS              RESTARTS   AGE
pod/default-http-backend-57fb4c77b4-ccmdx      1/1     Running   0          3m3s
pod/nginx-ingress-controller-7bfbcc484-khz6j   1/1     Running   0          2m44s

Ingress가 작동하려면, 클러스터는 실행 중인 Ingress Controller가 반드시 필요합니다.
위의 명령어로 nginx_ingress_controller를 설치했고, service,pod가 생성된 것을 확인할 수 있습니다.

Trouble shooting

위의 https://rwa.githubusercontent.com 경로대로 설치하면, Deployment의 apiVersion이 오류가 발생합니다.
Pod가 생성되지 않는 이슈가 있어, 해당 내용 중, Deployment의 apiVersion만 apps/v1으로 변경해 kubectl apply -f {{ file_name }} 을 실행했습니다.


Ingress 통해 접근하기

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo
spec:
  rules:
  - host: ch05.gihyo.local
    http:
      paths:
      - path: /
        backend:
          serviceName: echo
          servicePort: 80
$ kubectl apply -f simple-ingress.yaml
ingress.extensions/echo created

$ kubectl get ingress
NAME   CLASS    HOSTS              ADDRESS   PORTS   AGE
echo   <none>   ch05.gihyo.local             80      5s

$ curl http://localhost -H 'Host: ch05.gihyo.local'
Hello Docker!!%

curl 명령어를 통해 Pod까지 요청이 들어가는 것을 확인할 수 있습니다.


References

  • 도커 / 쿠버네티스를 활용한 컨테이너 개발 실전 입문
post-custom-banner

0개의 댓글