6 분 소요

📌 Topic

  • 2.1 배포를 통해 확인하는 파드(Pod)
  • 2.2 파드를 외부에서도 접속하게 하는 서비스
  • 2.3 파드와 디플로이먼트(Deployment) 차이
  • 2.4 외부로 노출하는 더 좋은 방법인 로드밸런서

01. 쿠버네티스에 실제로 앱 배포하기

이번 시간에는 쿠버네티스 환경을 통해 실제 Nginx 앱을 배포하는 시간을 갖는다.

01-1. 배포 프로세스

kube_deploy.PNG

쿠버네티스에 Application을 배포한다는 것은 master node를 통해 진행이 된다.
즉, kubectl을 통해 master node에 명령을 내리고 master node가 worker node에 app을 배포한다.
여기서 master node에 의해 배포가 되는 단위는 pod(파드)가 된다.

01-2. Pod란?

  • Pod란 하나의 일을하기 위한 컨테이너의 집합
  • 한 가지 일을 하는 단위를 구성한 것

02. Nginx 이미지 배포

위에서 Pod에 대한 개념을 간략히 알아보았다.
이제 control plain(마스터 노드)에서 Nginx 이미지를 실제 배포해보자.

02-1. nginx 이미지 배포 및 확인

# pod 배포를 위한 형식
# ex) kubectl run <Name> --imae=<이미지명>
# Deploy nginx image on pod
kubectl run nginx --image=nginx
  • 위 명령어를 통해 nginx 이미지를 배포한다
  • 해당 pod의 이름은 현재 nginx로 설정 하였다
# 현재 구동된 pod 목록 상세하게 확인
kubectl get po -o wide
# 목록 리스트
NAME    READY   STATUS    RESTARTS   AGE     IP             NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          2m59s   172.16.132.1   w3-k8s   <none>           <none>
  • nginx 이름을 가진 Pod가 worker node3번에 배포가 된것을 확인
  • 현재 IP는 172.16.132.1로 확인이 되는데 curl 명령어를 통해 실제 확인을 해보자
curl 172.16.132.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
  • curl 명령어를 통해 Nginx의 index.html 페이지 확인이 가능하다

03. 파드를 외부에서도 접속하게 하는 서비스

위에서 우리는 Nginx 이미지를 Kubernetes pod를 통해 배포하였지만 이러한 Pod에
직접 접근 해보지는 않았다. 이번 시간에는 Pod를 외부에 노출하기 위한 서비스 내용을 정리해보자.

03-1. 외부 접속 확인

서비스 작성을 하기에 앞서 외부(현재 로컬)에서 해당 Pod(172.16.132.1)에 접속이 가능한지
CMD 창을 통해 확인 해보자.

external_enter.PNG

해당 IP에 아래 명령어를 날렸는데 접속이 되지않는 것을 확인할 수 있다.
배포는 했다고 하는데 왜 이런 상황이 발생한 것일까?.. (당연한 부분임)

  • ping : x(접근 불가)
  • curl : x(접근 불가)

03-2. 현재 쿠버네티스 상태

current_kube_state.PNG

우선 쿠버네티스의 Pod를 외부에 노출하기 위해서는 앞쪽에 문이 필요하다.
하지만 현재는 Pod만 배포하고, 문을 배포하지 않은 상황이다.

이러한 문제를 해결하기 위한 방법을 여러가지가 존재한다.

  • 앞에 있는 문을 없애 버린다 (보안을 없애버린다는 의미)
  • 서비스 영역에 우리가 배포한 Pod(파드)를 연결한다

03-3. 서비스를 통해 외부 연결되는 파드 구성

# pod를 NodePort Type으로 노출
kubectl expose pod nginx --type=NodePort --port=80
  • 위 명령어를 통해 우리가 배포한 Pod(파드) ngix를 80 Port로 노출한다
  • 후에 서비스 명령어를 통해 실제 노출이 되었는지 확인 해보자
# 현재 kubernetes 서비스 확인
kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        95m
nginx        NodePort    10.105.244.38   <none>        80:31251/TCP   13s
  • Type이 NodePort인 nginx Pod가 보인다
  • PORT(S) 영역
    • 80: 컨테이너 내부 포트
    • 31251: 노출된 해당 컨테이너의 포트

서비스는 배포가 되었고, 해당 서비스를 통해 Nginx Pod가 외부에 노출된 것 역시 확인을 하였다.
그렇다면 지금부터 로컬 환경에서 해당 Pod에 직접 접속을 해보자.
접속을 하기 위해 worker node, pod(파드) 정보가 필요하다

# 현재 파드 정보 확인
kubectl get po -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          24m   172.16.132.1   w3-k8s   <none>           <none>
  • 현재 Nginx Pod는 w3-k8s 에 떠있는 상황이다
  • 다음으로는 w3-k8s의 정보를 알기 위해 node 정보를 조회 해보자
# 현재 노드 정보 확인
kubectl get no -o wide
NAME     STATUS   ROLES                  AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
m-k8s    Ready    control-plane,master   97m   v1.20.2   192.168.1.10    <none>        CentOS Linux 7 (Core)   3.10.0-1127.19.1.el7.x86_64   docker://19.3.14
w1-k8s   Ready    <none>                 93m   v1.20.2   192.168.1.101   <none>        CentOS Linux 7 (Core)   3.10.0-1127.19.1.el7.x86_64   docker://19.3.14
w2-k8s   Ready    <none>                 89m   v1.20.2   192.168.1.102   <none>        CentOS Linux 7 (Core)   3.10.0-1127.19.1.el7.x86_64   docker://19.3.14
w3-k8s   Ready    <none>                 85m   v1.20.2   192.168.1.103   <none>        CentOS Linux 7 (Core)   3.10.0-1127.19.1.el7.x86_64   docker://19.3.14
  • 여기서 주목해야 하는 부분은 w3-k8s의 INTERNAL-IP다
  • 해당 IP(192.168.1.103)와 위에서 조회한 Port(31251)를 통해 접속을 해보자
  • 위 내용은 개인마다 다를 수 있으니 실제 조회 정보를 통해 진행 해야 한다
# INTERNAL-IP + PORT(Expose)
http://192.168.1.103:31251/

local_nginx_web.PNG

  • 해당 HOST 정보를 통해 보이는 화면
  • Nginx Pod가 정상적으로 노출이 된 것을 의미한다

04. 파드와 디플로이먼트의 차이

이번에는 단일 파드가 아닌 파드를 여러 개 사용하는 경우 어떻게 해야하는지 정리 해보자.
Deployment를 이용하여 멀티 Pod를 구성할 것이다.

04-1. 현재 쿠버네티스 상태

deployment_pod_01.PNG

그림과 실제 내용은 다를 수 있습니다

현 상태의 쿠버네티스 파드는 워커 노드 중 하나에 배포가 되어 있는 상황이다. 만약 이 상황에서 1번 노드의 Pod(파드)가 죽으면 서비스에 문제가 생기게 된다. 여기서 우리가 원하는 것은 하나의 Pod가 아닌 여러개의 Pod가 존재하여 해당 Pod에 문제가 발생하여도 다른 Pod가 서비스를 받아 서비스를 유지하는 것이다.

04-2. 파드와 디플로이먼트 비교

  • 파드는 한개만 존재한다
  • 디플로이먼트는 여러개의 파드로 구성이 되어있다

deployment_kubectl.PNG

이전 kubectl 버전(1.16, 1.17)에서는 kubectl run으로 deployment를 배포할 수 있었다.
하지만 현재 1.18 버전 이후로는 kubectl run으로는 Pod만 배포할 수가 있고 deployment는
배포가 불가능하다.

그렇기에 현재는 kubectl create, kubectl apply를 통해 deployment를 배포해야 한다.
해당 명령어를 통해 Deployment Pod를 배포 해보자.

04-3. Deployment를 통한 Pod 배포

# nginx deployment 배포
kubectl create deployment deploy-nginx --image=nginx
deployment.apps/deploy-nginx created
# pod 상태 확인
kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
deploy-nginx-8458f6dbbb-vdzvm   1/1     Running   0          38s
nginx                           1/1     Running   0          48m
  • 현재 하나의 Pod가 배포된 것을 확인할 수 있다
  • 현재는 ReplicaSet(default 1)을 따로 설정하지 않았기 때문에 1개의 Pod만 존재한다

04-4. Deployment Pod Scale

# 기존 한 개의 Pod를 3개로 늘린다
kubectl scale deployment deploy-nginx --replicas=3
deployment.apps/deploy-nginx scaled
  • scale, —replicas=3 명령어를 통해 Pod의 개수를 지정한다
  • 이제 갯수가 실제로 늘어났는지 확인 해보자
kubectl get po
NAME                            READY   STATUS    RESTARTS   AGE
deploy-nginx-8458f6dbbb-f57qc   1/1     Running   0          79s
deploy-nginx-8458f6dbbb-rmdp5   1/1     Running   0          79s
deploy-nginx-8458f6dbbb-vdzvm   1/1     Running   0          4m51s
nginx                           1/1     Running   0          52m
  • 이전과는 다르게 deploy-nginx-84… 이 3개가 된 것을 확인 가능
  • Deployment는 yaml 파일로 빼서 관리하는 것이 좋을 것 같다

현재 디플로이먼트는 서비스로 노출하지 않은 상태이다
다음 시간에는 디플로이먼트(3개)를 외부에 노출 해보자

05. 외부로 노출하는 더 좋은 방법인 로드밸런서

이전 시간에 Pod가 모여 Deployment가 된다는 것을 배웠고, Deployment를 통해 Pod의 개수를 손쉽게 늘리는 것을 확인 하였다. 이번 시간에는 Deployment를 외부에 노출하는 방법에 대해 알아보자.

05-1. 디플로이먼트 노드 포트로 노출

# ex) expose <pod>
# ex) expose <deployment>
kubectl expose deployment deploy-nginx --type=NodePort --port=80
service/deploy-nginx exposed
  • 이전과 같이 expose 명령어를 사용하여 외부 노출을 진행
  • 배포가 되었는지 서비스 내역을 확인 해보자
# 현재 서비스 확인
kubectl get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
deploy-nginx   NodePort    10.108.200.244   <none>        80:30857/TCP   50s
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP        137m
nginx          NodePort    10.105.244.38    <none>        80:31251/TCP   42m
  • 이전 nginx와 마찬가지로, deploy-nginx가 노출이 되었다
http://192.168.1.101:30857
http://192.168.1.102:30857
http://192.168.1.103:30857
  • 이전과 같이 잘 배포가 된것을 확인할 수 있다
  • 하지만 디플로이먼트를 NodePort로 배포 하는게 꼭 좋은것은 아니다

디플로이먼트를 NodePort로 노출 한다는것은 해당 NodePort의 IP를 그대로 접속자들에게 알려주는 것과 동일하다. 즉, 대문의 비밀번호를 접속자에게 알려주는 것은 보안 상 상당히 위험한 행위다. 이러한 문제를 해결하기 위해서 로드밸런서를 사용하여 배포를 진행 해보자.

05-2. 노드포트보다 로드밸런서가 좋은 점

  • 노드포트는 IP를 직접 노출 해야 한다는 위험성이 존재
  • LB(Load Balancer)는 가야할 경로를 최적화 하여 구현이 가능하다
  • LB(Load Balancer)는 VIP(가상 IP)처럼, 고유 IP를 노출하지 않아도 된다

CNCF에서 제공하는 로드밸런서 배포를 통해 배포 진행

05-3. metallb 로드밸런서 배포

# kubernetes 로그밸런서 배포
kubectl apply -f ~/_Lecture_k8s_starter.kit/ch2/2.4/metallb.yaml
namespace/metallb-system created
podsecuritypolicy.policy/speaker created
serviceaccount/controller created
serviceaccount/speaker created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
role.rbac.authorization.k8s.io/config-watcher created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/config-watcher created
daemonset.apps/speaker created
deployment.apps/controller created
configmap/config created

CNCF Cloud Native Interactive Landscape

  • 이미 오픈 소스에 로드밸런서가 존재하여 해당 파일을 배포한다
  • 로드밸런서는 CNCF의 metallb를 사용한다

05-4. chk-hn pod 개수 조정

kubectl scale deployment chk-hn --replicas=3
deployment.apps/chk-hn scaled
kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
chk-hn         1/3     3            1           62s
deploy-nginx   3/3     3            3           38m
  • chk-hn Pod의 개수를 1개에서 3개로 늘렸다

05-5. Deployment 서비스 노출

kubectl expose deployment chk-hn --type=LoadBalancer --port=80
service/chk-hn exposed
  • deplyment 서비스 노출
kubectl get svc
NAME           TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE
chk-hn         LoadBalancer   10.97.11.31      192.168.1.11   80:30377/TCP   42s
deploy-nginx   NodePort       10.108.200.244   <none>         80:30857/TCP   27m
kubernetes     ClusterIP      10.96.0.1        <none>         443/TCP        164m
nginx          NodePort       10.105.244.38    <none>         80:31251/TCP   69m

06. 배포한 것들 삭제하기

위에서 배포한 모든 내용들을 삭제한다.

05-1. 삭제 진행

kubectl delete service chk-hn
kubectl delete service nginx
kubectl delete service deploy-nginx
kubectl delete deployment deploy-nginx
kubectl delete pod nginx
kubectl delete -f ~/_Lecture_k8s_starter.kit/ch2/2.4/metallb.yaml
...

참고 자료

댓글남기기