GKE을 사용하여 완전한 Kubernetes 클러스터를 provision
kubectl
을 사용하여 Docker 컨테이너를 배포/관리
Kubernetes의 배포와 서비스를 사용하여 어플리케이션을 microservices로 분할
하나의 서버에 다양한 기능이 위치해있는 구조
➡ 즉, 하나의 프로젝트에 코드가 모여있고 하나의 파일로 구성됨
👍장점
👎단점
최소한의 의존성
을 가진다.Kubernetest는 어플리케이션에 중점!
이번 lab에서는 app
이라는 예제 어플리케이션을 사용!
Note) App은 Github에서 호스팅되면 12요소 예시 어플리케이션 제공
이번 lab에서는 다음의 Docker 이미지를 다룬다.
- kelseyhightower/monolith - monolith는 auth 및 hello 서비스 포함
- kelseyhightower/auth - auth microservice로, 인증된 사용자를 위한 JWT 생성
JWT(JSON Web Token)
: 유저를 인증하고 식별하기 위한 토큰(Token)기반 인증 참고- kelseyhightower/hello - hello microservice로, 인증된 사용자를 안내
- ngnix - auth 및 hello 서비스의 프론트앤드
nginx
: 동시접속 처리에 특화된 웹 서버 프로그램
Kubernetes
이번 Lab에서는 Kubernetes Engine과 같은 managed environment을 사용하여 기본 인프라를 설정하기보다는 Kubernetes를 경험하는 데 집중해보자!
실습 시작 전에 개요에서 설정 및 요구사항
까지 완료된 상태여야 한다!
$ gcloud config set compute/zone us-central1-b
$ gcloud container clusters create io
$ gsutil cp -r gs://spls/gsp021/* .
실습에 필요한 디렉토리로 변경
$ cd orchestrate-with-kubernetes/kubernetes
파일을 나열하여 작업 중인 파일 확인
$ ls
Kubernetes를 시작하는 가장 쉬운 방법은 kubectl create
명령어를 사용하는 것!
kubectl create
을 사용하여 nginx 컨테이너의 단일 인스턴스 실행$ kubectl create deployment nginx --image=nginx:1.10.0
Kubernetes에서 모든 컨테이너는 pod에서 실행된다.
$ kubectl get pods
nginx 컨테이너가 실행되면 kubectl expose
명령어를 사용하여 Kubernetes 외부로 노출시킬 수 있음
$ kubectl expose deployment nginx --port 80 --type LoadBalancer
$ kubectl get services
$ curl http://<External IP>:80
Kubernetes는 kubectl
실행 및 노출 명령어로 바로 사용할 수 있는 간편한 워크플로 지원
Kubernetes의 핵심은 Pod
Pod는 1개 이상의 컨테이너가 포함된 모음
일반적으로 상호 의존성이 높은 컨테이너가 여러 개 있으면 이를 하나의 Pod에 패키징
pod는 콘텐츠에 공유된 네임스페이스 제공
➡ 즉, 이 예시의 포드 안에 있는 2개의 컨테이너는 서로 통신 가능하며, 첨부된 volumes도 공유
pod는 네트워크 네임스페이스도 공유
➡ 즉, pod는 IP 주소를 1개씩 소유
pod는 pod 구성(configuration) 파일을 사용하여 생성 가능!
$ cat pods/monolith.yaml
$ kubectl create -f pods/monolith.yaml
$ kubectl get pods
$ kubectl describe pods monolith
Kubernetes를 사용하면
➡ 이제 deployment에 필요한 모든 pods를 생성 가능!
pod에는 기본적으로 비공개 IP 주소가 부여되며, 클러스터 밖에서는 접근 불가.
kubectl port-forward
명령어를 통해 local port를 monolith pod 안의 port로 mapping
(여기서부터 port 간 통신을 설정하기 위해 여러 Cloud Shell 탭 사용)
$ kubectl port-forward monolith 10080:80
$ curl http://127.0.0.1:10080
$ curl http://127.0.0.1:10080/secure
$ curl -u user http://127.0.0.1:10080/login
$ TOKEN=$(curl http://127.0.0.1:10080/login -u user|jq -r '.token'
$ curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:10080/secure
$ kubectl logs monolith
$ kubectl logs -f monolith
curl
을 사용하여 monolith pod와 상호작용했다면, 세 번째 터미널에서 로그가 업데이트 되는 것을 확인 가능$ curl http://127.0.0.1:10080
$ kubectl exec monolith --stdin --tty -c monolith /bin/sh
ping
명령어를 사용하여 외부 연결 테스트 가능!$ ping -c 3 google.com
$ exit
pod와의 상호작용은 kubectl
명령을 사용하는 것만큼 쉽다.
원격으로 컨테이너를 조회하거나 로그인 셸이 필요한 경우, Kubernetes가 작업에 필요한 모든 것을 제공!
Pod는 영구적으로 지속되지 않는다.
활성 여부 또는 준비 상태 검사 오류와 같은 다양한 이유로 중지되거나 시작될 수 있으며, 이로 인해 문제가 발생한다.
Pod 집합과 통신해야 하는 경우 어떻게?
Pod가 다시 시작되면 IP 주소가 변경될 수 있다.
➡ 이와 같은 상황에서 Services가 유용!
서비스는 pod를 위해 stable한 endpoints 제공
서비스는 labels을 사용하여 어떤 pod에서 작동할지 결정
pod에 label이 정확히 지정되어 있다면 서비스가 이를 자동으로 감지하고 노출시킨다.
서비스가 제공하는 pod 집합에 대한 액세스 수준은 서비스 유형에 따라 다르다.
ClusterIP
(내부)NodePort
LoadBalancer
이제 서비스를 생성해보고, label selectors를 사용하여 제한된 pod 집합을 외부에 노출하는 작업을 수행해보자!
서비스를 생성하기 전, https 트래픽을 처리할 수 있는 보안이 설정된 pod를 생성하자!
현재 디렉터리는 ~/orchestrate-with-kubernetes/kubernetes
여야 한다.
$ cat pods/secure-monolith.yaml
kubectl create secret generic tls-certs --from-file tls/
kubectl create configmap nginx-proxy-conf --from-file nginx/proxy.conf
kubectl create -f pods/secure-monolith.yaml
이제 보안이 설정된 pod가 있으니 이를 외부로 노출시키자.
이를 위해 Kubernetes 서비스를 만들어야 한다.
$ cat services/monolith.yaml
app: monolith
, secure: enabled
라벨이 지정된 pod를 자동으로 찾고 노출시키는 역할을 하는 selector가 있다.$ kubectl create -f services/monolith.yaml
서비스를 노출하기 위해 port 사용
➡ 다른 앱이 서버 중 하나에 port 31000과 연결을 시도하면 port 충돌 발생 가능
일반적으로 port 할당은 Kubernetes가 처리
이번 lab에서는 port를 선택했기 때문에 추후 상태 확인(health checks)을 더 쉽게 설정 가능
$ gcloud compute firewall-rules create allow-monolith-nodeport \ --allow=tcp:31000
이제 설정이 완료되었으니 port 전달 없이 클러스터 밖에서 안전한 monolith service를 조회할 수 있다.
$ gcloud compute instances list
$ curl -k https://<EXTERNAL-IP>:31000
현재 monolith service에는 endpoints가 없다.
➡ 이 문제를 해결하기 위한 방법 중 하나는 label query와 함께 kubectl get pods
명령어 사용하는 것
$ kubectl get pods -l "app=monolith"
$ kubectl get pods -l "app=monolith,secure=enabled"
$ kubectl label pods secure-monolith 'secure=enabled'
$ kubectl get pods secure-monolith --show-labels
$ kubectl describe services monolith | grep Endpoints
$ gcloud compute instances list curl -k https://<EXTERNAL_IP>:31000
📌 이번 Lab의 목표
: production에 있는 container들을 확장하고 관리하는 것
➡ Deployments가 유용!
👍 Deployments의 주요 이점
Deployments의 역할
간단한 예를 살펴보자.
pod는 생성 기반 노드의 전체 기간과 연결되어 있다.
위의 예시에서 Node3이 중단되면서 pod도 중단된 걸 볼 수 있다.
직접 새로운 pod를 만들고 이를 위한 노드를 찾는 대신, deployments가 새로운 pod를 만들고 Node2를 실행한 것을 볼 수 있다.
➡ 아주 편리한 방식!
pod와 서비스에 관해 배운 모든 지식을 바탕으로, 이제 deployments를 사용하여 monolith 어플리케이션을 작은 서비스로 분할해보자!
monolith 앱을 3가지 부분으로 나누자.
auth
: 인증된 사용자를 위한 JWT 토큰 생성hello
: 인증된 사용자를 안내frontend
- 트래픽을 auth 및 hello 서비스로 전달각 서비스용 deployments를 만들 준비가 되었다.
auth 및 hello deployments용 내부 서비스와 frontend deployment용 외부 서비스를 정의해보자.
➡ 이렇게 하면 Monolith와 같은 방식으로 microservices와 상호작용 할 수 있으며, 각 서비스를 독립적으로 확장하고 배포 가능
$ cat deployments/auth.yaml
kubectl create
명령어를 통해 auth deployment를 생성하면, deployment manifest 데이터를 준수하는 pod가 생성된다.
➡ 즉, replica 필드에 명시된 숫자를 변경하여 pod 개수 조정 가능
$ kubectl create -f deployments/auth.yaml
$ kubectl create -f services/auth.yaml
$ kubectl create -f deployments/hello.yaml
$ kubectl create -f services/hello.yaml
$ kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf
$ kubectl create -f deployments/frontend.yaml
$ kubectl create -f services/frontend.yaml
$ kubectl get services frontend
$ curl -k https://<EXTERNAL-IP>