이번 실습에서는 다음과 같은 과정을 배운다.
- 쿠버네티스 클러스터를 만들고, 클러스터 상에서 Docker 컨테이너를 배포하고 관리한다.
- Kubernetes의 디플로이먼트 및 서비스를 이용하여 애플리케이션을 배포한다.
작업 1. 샘플 코드 가져오기
먼저 Cloud Shell 명령줄에서 GitHub 저장소를 클론한 후, 해당 디렉토리로 변경한다.
gsutil cp -r gs://spls/gsp021/* . # 샘플 코드 클론하기
cd orchestrate-with-kubernetes/kubernetes # 해당 디렉토리로 이동
ls
명령어를 통해 파일을 나열해보면 다음과 같은 파일들이 존재하는 것을 알 수 있다.
ls
>>>
deployments/ /* 배포를 위한 파일들 */
...
nginx/ /* nginx 구성 파일들 */
...
pods/ /* 쿠버네티스 pod를 위한 파일들 */
...
services/ /* 쿠버네티스 서비스를 위한 파일들 */
...
tls/ /* TLS 인증서 */
...
cleanup.sh /* 정리 스크립트 */
각 파일들에 대해서는 실습을 진행하면서 더 자세히 알아보도록 하고, 우선은 넘어가보자.
작업 2. 간략한 Kubernetes 데모 생성
Kubernetes를 시작하는 가장 쉬운 방법은 kubectl create
명령어를 사용하는 것이다(라고 Skill Boost가 말했다). kubectl
의 뜻을 풀어서 보면 kubernetes control이라는 뜻인데, 이 말 그대로 쿠버네티스의 상태를 확인하고 컨트롤하기 위해 사용되는 명령어 인터페이스라고 생각하면 된다. 이 중 kubectl create
명령어를 통해서는 배포(deployment), 서비스(service), 파드(pod) 등을 생성할 수 있다. 지금 이 실습에서는 nginx 배포를 생성하기 위해 kubectl
를 사용하고 있다.
kubectl create deployment nginx --image=nginx:1.10.0 # nginx 배포를 생성한다.
kubectl get pods # pod가 생성된 결과를 확인 가능하다.
Kubernetes가 배포를 생성했고, kubectl get pods
명령어를 통해서 확인해보면 pod가 생성된 것을 알 수 있다.
그렇다면 배포는 무엇이고, pod는 또 어떤 걸까?
일반적으로 애플리케이션을 빌드하고 새로운 빌드 버전을 사용자에게 전달하는 것을 배포라고 한다. Kubernetes 상에서도 이 배포의 의미는 같지만, 해당 어플리케이션의 빌드된 이미지가 실행되고 있는 컨테이너의 집합인 pod가 생성되어 배포된다는 점이 다르다. 즉, 어플리케이션 이미지는 컨테이너 안에 들어가 있고, 여러 개의 컨테이너 집합은 pod안에 들어가 있으며, 이 pod를 생성하는 과정을 배포라고 한다. 또한, 이러한 pod는 worker node안에서 생성된다. 전체적인 구조를 이미지로 보면 다음과 같다.
kubernetes의 전체적인 구조는 처음 배우는 사람이라면 좀 복잡할 수 있다(심지어 위의 그림은 worker node 하나만 설정한 것이다. 쿠버네티스의 전체적인 구조는 이것보다 더 복잡하다). 하지만 지금 확실히 알고 넘어가야 하는 점은 단 2가지다. 1) 배포 덕분에 pod가 작동하고 있으며, 2) 워커 노드에 오류가 발생해도 pod는 계속해서 작동한다는 점이다.
위의 명령어들을 통해 nginx 컨테이너를 실행하고 이를 확인했으면, kubectl expose
명령어를 사용하여 Kubernetes 서비스를 외부로 노출시킬 수 있다.
kubectl expose deployment nginx --port 80 --type LoadBalancer # 서비스를 외부에 노출
kubectl get services # 서비스 확인
방금 일어난 일은 다음과 같다. kubectl expose
명령어를 사용하자 Kubernetes가 백그라운드에서 외부 IP 주소가 첨부된 로드 밸런서를 만들었다. 이제 이 외부 IP 주소를 조회하는 모든 클라이언트는 서비스 백그라운드에 있는 파드-즉, nginx 파드로 라우팅된다.
쿠버네티스에서는 애플리케이션 컨테이너가 실행 중인 파드를 만들었다고 바로 다른 사용자들이 해당 파드에 접근할 수 있는 것이 아니다. 해당 파드를 서비스(service)해야 접근 가능해진다. 쿠버네티스에서 서비스를 생성할 수 있는 방법에는 3가지가 있는데, 이 실습에서는 그 중 로드 밸런서를 사용하여 외부 IP를 만들어 주었다.
참고로 생성된 서비스의 External IP 필드가 채워지는 데는 몇 분 정도 소요될 수 있다. 채워지기 전에는 위의 그림처럼 <pending>
상태에 놓여 있다가, 생성된 후에는 34.72.21.11
처럼 채워진 것을 볼 수 있다.
만들어진 Nginx 컨테이너를 조회하고 싶으면 외부 IP에 curl
을 때리면 된다.
curl http://<External IP>:80
물론, 외부 IP가 생성되었으므로 웹 브라우저에서 직접 웹페이지를 볼 수도 있다. 해당 IP로 들어가보면 다음과 같은 nginx 페이지가 출력된다. (당연히 모든 사람이 나랑 똑같은 34.72.21.11 주소를 가지는 건 아니다. 외부 IP 주소는 랜덤하게 생성된다)
작업 3. 파드 만들기
위에서 언급한 것처럼, 파드는 컨테이너의 집합을 의미한다. 일반적으로 상호 의존성이 높은 컨테이너가 여러 개 있을 경우 이를 하나의 파드에 패키징하여 관리를 편리하게 만든다.
위 실습에서 만들었던 파드에는 nginx 컨테이너만 있었지만, 앞으로 진행할 실습에는 모놀리식 컨테이너도 같이 생성된다. 하나의 파드에 속하는 두 개 이상의 컨테이너에는 어떤 특징이 있을까?
- 파드에는 볼륨이라는 것이 포함되어 있는데, 이는 파드가 존재하는 한 계속해서 존재하며 파드에 포함된 컨테이너에 의해 사용될 수 있는 데이터 디스크이다. 같은 파드 안에 속하는 컨테이너들은 파드에 첨부된 볼륨을 공유한다.
- 파드는 또한 공유된 네임스페이스를 제공한다. 즉, 이 예시의 파드 안에 있는 2개의 컨테이너는 서로 통신할 수 있다.
- 또한 파드는 네트워크 네임스페이스도 공유한다. 즉, 파드는 IP 주소를 1개씩 갖고 있다.
더 자세한 이야기는 다른 글에서 다루도록 하고, 파드를 만드는 방법에 대해서 살펴보자. 파드는 파드 구성 파일을 사용하여 만들 수 있다. 모놀리식 포드 구성 파일을 살펴보면 다음과 같이 출력된다.
cat pods/monolith.yaml
apiVersion: v1
kind: Pod
metadata:
name: monolith
labels:
app: monolith
spec:
containers:
- name: monolith
image: kelseyhightower/monolith:1.0.0
args:
- "-http=0.0.0.0:80"
- "-health=0.0.0.0:81"
- "-secret=secret"
ports:
- name: http
containerPort: 80
- name: health
containerPort: 81
resources:
limits:
cpu: 0.2
memory: "10Mi"
여기서 주목해야 할 부분은 다음과 같다.
- 포드가 1개의 컨테이너(
monolith
)로 구성되어 있다. - 시작할 때 컨테이너로 몇 가지 인수(
args
)가 전달된다 HTTP
트래픽용으로 포트 80이 개방된다.
파일 내용을 확인해 보았으니, 이제 kubectl
을 사용하여 모놀리식 포드를 만들어보자. 위에서 배포를 생성할 때 했던 것과 마찬가지로 kubectl create
를 사용해주면 된다(참고로 kubectl create -f
명령에서 -f
는 "file"을 의미한다. 이 옵션은 쿠버네티스 리소스를 정의하는 YAML 또는 JSON 형식의 파일을 지정하는데 사용된다).
kubectl create -f pods/monolith.yaml # 파드 만들기
kubectl get pods # 파드 내용 확인
참고로 모놀리식 파드를 실행하기 위해서 Docker Hub에서 모놀리식 컨테이너 이미지를 가져오게 된다. 포드가 실행되면 kubectl describe
명령어를 사용하여 모놀리식 포드에 관해 자세히 알아보자.
kubectl describe pods monolith
파드 IP 주소 및 이벤트 로그를 포함한 모놀리식 포드에 관한 여러 정보가 표시된다. 이 정보는 디버깅 시 유용하게 사용될 수 있다. 이렇게 Kubernetes를 사용하면 구성 파일을 통해 간편하게 파드를 만들 수 있으며, 파드가 실행 중일 때 정보를 쉽게 확인할 수 있다.
작업 4. 파드와 상호작용하기
파드에는 기본적으로 비공개 IP 주소가 부여되며 클러스터 밖에서는 접근할 수 없다(그래서 위에서는 로드 밸런서로 서비스를 만들어서 파드에 접근했다). kubectl port-forward
명령어를 사용하여 로컬 포트를 모놀리식 포드 안의 포트로 매핑해 파드에 접근해보자.
📌 참고: 포트 포워딩이란?
Kubernetes 클러스터 내에서 실행중인 애플리케이션에 접근하려면, 일반적으로 서비스를 사용하여 접근한다. 서비스는 로드 밸런싱 등의 방식으로 만들 수 있다.
하지만 때로는 직접 파드에 접근하여 애플리케이션을 디버깅하거나 테스트해야 하는 경우가 있다. 이 경우 포트 포워딩을 사용하여 로컬 컴퓨터에서 파드에 직접 접근할 수 있다. 이때 포트 포워딩은 로컬 컴퓨터의 포트를 Kubernetes 클러스터 내의 포트로 매핑하는 프로세스로, 이를 통해 로컬 컴퓨터에서 Kubernetes 클러스터 내의 애플리케이션에 직접 접근할 수 있다.
Cloud Shell 터미널 2개를 열어서 하나는 kubectl port-forward
명령어를 실행하고 다른 하나는 curl
명령어를 실행해보자.
kubectl port-forward monolith 10080:80 # 첫 번째 터미널에서 실행
curl <http://127.0.0.1:10080> # 두 번째 터미널에서 실행
그럼 컨테이너가 친절하게도 {"message": "Hello"}
라고 인사를 건네는 것을 확인할 수 있다. 이제 다시 curl
명령어를 사용하여 이번에는 보안이 설정된 엔드포인트를 조회해보자.
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> # 토큰을 통한 인증
Enter host password for user 'user'
라는 메세지가 뜨면 비밀번호 'password'를 사용하여 로그인한다. 로그인이 성공적으로 완료되면 JWT 토큰이 출력되는데, 이 토큰을 환경 변수로 만든 후 이 토큰으로 curl을 사용하여 보안이 설정된 엔드포인트를 조회한다. 그럼 정상적으로 {"message": "Hello"}
메세지를 얻을 수 있다.
kubectl logs
명령어를 사용해 monolith 포드의 로그를 확인해보자.
kubectl logs monolith
로그를 확인했으면 이제 세 번째 터미널을 열고 -f
플래그를 사용하여(-f
는 follow
를 의미) 실시간 로그 스트림을 가져와보자. 첫 번째 터미널에서 curl을 사용하여 모놀리식 pod와 상호작용하고 있다면 세 번째 터미널에서 로그가 업데이트되는 것을 확인할 수 있다.
kubectl logs -f monolith
로그를 다 확인했으면 이제 kubectl exec
명령어를 사용하여 모놀리식 포드의 대화형 셸을 실행해보자. 가끔 컨테이너 내부에 직접 들어가서 터미널 명령어를 치며 문제의 원인을 파악하고 해결하고 싶을 때가 있는데, 그럴 때 사용되는 게 바로 kubectl exec
명령어이다. 셸을 실행한 후 ping
명령어를 사용하면 외부 연결을 테스트해볼 수 있다.
kubectl exec monolith --stdin --tty -c monolith /bin/sh
/ # ping -c 3 google.com # 컨테이너 내부에서 셸 실행
>> 64 bytes from ...
참고로 위 명령어의 옵션들은 다음과 같다.
--stdin
: 컨테이너의 표준 입력(stdin)을 허용하는 옵션으로, 이 옵션을 사용하면 셸을 실행한 후 사용자가 명령을 입력할 수 있다.--tty
: 할당된 유사 터미널(tty)을 사용하는 옵션으로, 이 옵션을 사용하면 터미널과 같은 인터랙티브한 환경을 제공한다.-c monolith
: 파드 내의 특정 컨테이너를 선택하는 옵션으로, 이 옵션을 사용하여 여러 개의 컨테이너를 가진 파드에서 특정 컨테이너를 실행할 수 있다. 여기서는 monolith 컨테이너를 실행한다./bin/sh
: 실행할 명령어또는 셸로, 여기서는 /bin/sh를 실행하여 파드 내의 monolith 컨테이너에서 셸을 실행한다.
대화형 셸 사용을 완료한 후에는 반드시 exit 명령어를 통해 로그아웃해야 한다. 그렇지 않으면 원래의 환경으로 돌아올 수 없다.
exit
작업 5. 서비스 만들기
우리는 여태까지 파드를 만들어 어플리케이션을 작동하게 했다. 그런데 문제는 파드는 영구적으로 지속되지 않는다는 것이다. 에러나 비활성화 등의 다양한 이유로 중지되거나 시작될 수 있으며 이로 인해 문제가 발생할 수 있다.
위에서 파드에는 비공개 IP가 부여된다고 말했다. 이 IP는 누가 부여해주는 것일까? 바로 kubernetes가 랜덤하게 생성해주는 IP이다. 따라서 파드가 다시 시작되면 IP 주소 또한 바뀌는 문제가 생길 수 있다. 이때 파드를 위해 안정적인 엔드포인트를 제공해주는 것이 바로 서비스(service)이다.
그렇다면 서비스는 어떻게 파드가 죽었다가 다시 살아나도 이를 감지하고 엔드포인트를 제공해 줄 수 있을까? 서비스는 라벨(label)을 사용하여 어떤 포드에서 작동할지 결정할 수 있다. 포드에 라벨이 정확히 지정되어 있다면 서비스가 이를 자동으로 감지하고 노출시킨다.
위에서 로드 밸런서 실습을 할 때 쿠버네티스에서 서비스를 생성할 수 있는 방법에는 3가지가 있다고 말했는데, 좀 더 정확하게 말하자면 외부로 서비스를 노출할 수 있는 방법에 3가지가 있고, 바로 그 3가지 유형은 다음과 같다.
ClusterIP
: 사용자에게 서비스를 제공하기 위한 용도가 아니다. 클러스터 안에서만 확인 가능하다.NodePort
: 클러스터의 각 노드에 외부에서 액세스 가능한 IP 주소를 제공한다.LoadBalancer
: 클라우드 제공업체로부터 로드 밸런서를 추가하여 서비스에서 유입되는 트래픽을 내부에 있는 노드로 전달하는 역할을 한다.
이 외에도 Ingress
라는 특별한 서비스 매카니즘이 있긴 한데, 이는 yaml 파일에서 kind: Service
가 아니라 kind: Ingress
로 분류되는 좀 특별한 친구이다. 이에 대해서는 나중에 다루도록 하고, 일단 지금은 NodePort를 사용해 서비스를 생성해보자.
서비스를 만들기 전에 ~/orchestrate-with-kubernetes/kubernetes 디렉토리로 다시 돌아간 후, https 트래픽을 처리할 수 있는 보안이 설정된 포드를 만들어 보자.
cd ~/orchestrate-with-kubernetes/kubernetes
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
이제 보안이 설정된 포드가 있으니 이를 외부로 노출시킨다. 그러기 위해서는 Kubernetes 서비스를 만들어야 한다. 우선 서비스 설정 파일의 구성을 한번 살펴보자.
cat services/monolith.yaml
kind: Service
apiVersion: v1
metadata:
name: "monolith"
spec:
selector:
app: "monolith"
secure: "enabled"
ports:
- protocol: "TCP"
port: 443
targetPort: 443
nodePort: 31000
type: NodePort
여기서 주목해야 할 부분은 다음과 같다.
app: monolith
및secure: enabled
라벨이 지정된 포드를 자동으로 찾고 노출시키는 선택기(selector)가 존재한다.- 외부 트래픽을 포트 31000에서 포트 443의 nginx로 전달하기 위해 NodePort를 노출시키고 있다.
이제 kubectl create 명령어를 사용하여 모놀리식 서비스 구성 파일에서 모놀리식 서비스를 만들어보자.
kubectl create -f services/monolith.yaml
NodePort 31000은 nginx를 통해 사용 중이기 때문에, 만약 다른 앱이 포트 31000과 연결을 시도하면 포트 충돌이 발생할 수 있다. 일반적으로 포트 할당은 Kubernetes가 처리하는데 이 실습에서는 특정 포트를 직접 선택했기 때문에 추후 더 쉽게 상태 확인을 설정할 수 있다.
완료된 작업 테스트하기
완료된 작업을 테스트하기 위해 외부에서 어플리케이션에 접근하고자 한다. 우선 외부 트래픽을 허용하기 위해서 GCP의 방화벽 차단을 해제해주자. gcloud compute firewall-rules
명령어를 사용하여 트래픽을 노출된 NodePort의 모놀리식 서비스로 보낸다.
gcloud compute firewall-rules create allow-monolith-nodeport \\
--allow=tcp:31000
31000번 포트로 tcp 트래픽을 허용하는 방화벽 규칙 allow-monolith-nodeport
이 생성되었다. 이제 설정이 완료되었으니 포트 포워딩 없이도 클러스터 밖에서 모놀리식 서비스를 조회할 수 있다.
먼저 노드 1개의 외부 IP 주소를 가져오고, curl을 사용하여 보안이 설정된 모놀리식 서비스를 조회해보자.
gcloud compute instances list
curl -k https://<EXTERNAL_IP>:31000
그런데 connection refused 에러가 뜨면서 curl이 작동하지 않았다. 이유가 뭘까? 바로 pod에 라벨(label)이 적절하게 설정되지 않았기 때문이다.
작업 6. 포드에 라벨 추가하기
kubectl get pods 명령어와 라벨 쿼리를 같이 활용하면 해당 라벨을 가지고 있는 파드를 확인할 수 있다. kubectl get pods -l "app=monolith"
명령어를 치면 모놀리식 라벨이 지정되어 실행되는 포드가 있다는 사실을 확인할 수 있다. 그런데 app=monolith
와 secure=enabled
를 동시에 가지고 있는 파드는 어떨까? 해당 라벨 쿼리로는 결과가 출력되지 않는다. 그런데 우리가 앞서 서비스를 만들 때는 두 라벨을 모두 가지고 있는 파드를 인식하도록 만들어 주었으므로, 파드에 secure=enabled
라벨을 추가해야 한다.
kubectl get pods -l "app=monolith"
kubectl get pods -l "app=monolith,secure=enabled"
kubectl label 명령어를 사용하면 특정 파드에 라벨을 추가할 수 있다. 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
성공적으로 Hello 메세지를 받는 것을 확인할 수 있다. 물론, 이제 엔드포인트가 생성되었으므로 직접 웹 브라우저에서 확인할 수도 있다.
작업 7. 디플로이먼트 만들기
방금 전 우리는 pod의 yaml 파일을 통해 파드를 생성해주었고, 해당 파드에 service를 연결해 외부에서 조회 가능한 엔드포인트를 만들어 주었다. 그런데 맨 처음에 했던 했던 간략한 Kubernetes 데모 생성 실습을 생각해보면 하나의 배포(deployment)만 생성해서 nginx 웹페이지를 브라우저에서 조회하는 게 가능했다.
그 이유는 디플로이먼트는 실행 중인 포드의 개수가 사용자가 명시한 포드 개수와 동일하게 만드는 선언적 방식이기 때문이다. 배포를 사용하면 어떤 pod를 가질 것인지, 해당 pod를 몇 개 가질 것인지를 편리하게 관리할 수 있다.
배포는 백그라운드에서 replicaset(한국어로는 복제본 집합)을 사용하여 pod의 시작 및 중지를 관리한다. Pod를 업데이트하거나 확장해야 하는 경우 배포가 이를 처리할 수 있다. 또한 디플로이먼트는 어떤 이유로든 포드가 중지되면 재시작을 담당하여 처리한다.
아래의 간단한 예시를 살펴보자.
위 예시에서는 Node3이 중단되면서 포드도 중단되었다. 그러나 관리자가 직접 새로운 포드를 만들고 이를 위한 노드를 찾는 일을 할 필요 없이 디플로이먼트가 알아서 새로운 포드를 만들고 Node2에서 실행했다. 굉장히 편리한 방식이다.
이러한 일이 가능한 이유는 쿠버네티스는 특정한 상태(state)를 유지하는 것을 목표로 하기 때문이다. 만약 hello라는 파드를 3개 실행할 것을 디플로이먼트 yaml 파일에서 명시해주면, 에러나 장애로 인해 파드 또는 노드가 다운되더라도 반드시 '3개의 파드가 실행 중인 상태'를 유지하기 위해 쿠버네티스가 알아서 처리해준다.
이제 쿠버네티스의 파드와 서비스, 그리고 배포까지 배워보았으니, 디플로이먼트를 사용하여 모놀리식 애플리케이션을 작은 서비스로 분할해 보자.
모놀리식 앱을 다음의 3가지 부분으로 나눈다.
- auth - 인증된 사용자를 위한 JWT 토큰을 생성
- hello - 인증된 사용자를 안내
- frontend - 트래픽을 auth 및 hello 서비스로 전달
각 디플로이먼트를 만들고, auth 및 hello 디플로이먼트용 내부 서비스와 frontend 디플로이먼트용 외부 서비스를 정의하자. 이렇게 하면 모놀리식과 같은 방식으로 마이크로서비스와 상호작용할 수 있으며, 각 서비스를 독립적으로 확장하고 배포할 수 있다(모놀리식은 모든 관련 사항을 하나로 결합하는 코드 베이스를 뜻하고, 마이크로서비스는 각 세부적인 기능당 하나의 서비스로 분할하는 방식을 뜻한다).
먼저 auth 디플로이먼트 구성 파일을 검토해보자.
cat deployments/auth.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth
spec:
selector:
matchlabels:
app: auth
replicas: 1
template:
metadata:
labels:
app: auth
track: stable
spec:
containers:
- name: auth
image: "kelseyhightower/auth:2.0.0"
ports:
- name: http
containerPort: 80
- name: health
containerPort: 81
resources:
limits:
cpu: 0.2
memory: "10Mi"
livenessProbe:
httpGet:
path: /healthz
port: 81
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /readiness
port: 81
scheme: HTTP
initialDelaySeconds: 5
timeoutSeconds: 1
여기서 주목해야 할 부분은 다음과 같다.
- 디플로이먼트가 파드 복제본(replicas) 1개를 만든다. 해당 파드는 auth 컨테이너 2.0.0 버전을 사용한다.
kubectl create 명령어를 실행하여 auth 디플로이먼트를 만들면 해당 설정을 준수하는 배포가 만들어진다. 즉, 복제본 필드에 명시된 숫자만큼의 pod가 항상 실행 중일 것을 보장하는 배포가 생성된다. replicas
필드를 변경하면 포드 숫자를 조정할 수 있다.
이를 참고하여, 각각 auth/hello/frontend 용 배포와 서비스를 생성해보자.
# auth 파드용 배포와 서비스 생성
kubectl create -f deployments/auth.yaml
kubectl create -f services/auth.yaml
# hello 파드용 배포와 서비스 생성
kubectl create -f deployments/hello.yaml
kubectl create -f services/hello.yaml
# frontend 파드용 배포와 서비스 생성
kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf
kubectl create -f deployments/frontend.yaml
kubectl create -f services/frontend.yaml
이때 frontend를 만들기 위해서는 컨테이너에 구성 데이터를 보관해야 하기 때문에 다른 배포와는 다르게 추가적인 단계가 필요하다.
create configmap
: ConfigMap을 생성하는 명령어. ConfigMap은 쿠버네티스에서 설정 데이터를 저장하고 관리하기 위한 리소스이다. 설정 데이터는 애플리케이션의 동작을 제어하는 데 사용되는 환경 변수, 설정 파일, 명령어 인자 등을 포함할 수 있다.nginx-frontend-conf
: 생성될 ConfigMap의 이름. 여기서는 nginx-frontend-conf라는 이름을 사용한다.--from-file=nginx/frontend.conf
: ConfigMap에 포함될 데이터를 지정하는 옵션. nginx/frontend.conf 파일의 내용을 ConfigMap에 포함시킨다.
여기서는 깊게 다루지는 않지만, frontend.conf 파일에는 Nginx 서버에서 hello 서비스와 auth 서비스에 대한 로드 밸런싱 및 프록시 설정 등이 저장되어 있다.
설정을 마쳤으니 이제 frontend의 외부 IP 주소를 알아내고, curl 명령어를 사용하여 frontend와 상호작용하자(참고: 외부 IP 주소가 생성되는 데 몇 분 정도 걸릴 수 있다).
kubectl get services frontend
그러면 hello 응답을 받게 된다👋