쿠버네티스 기본 개념에 대해 알아보려고 한다.

 

Pod

쿠버네티스 노드는 여러 Pod로 구성될 수 있고, 각 Pod는 여러 Container를 가질 수 있다.

@cloudshell:~ (proud-curve)$ kubectl explain pods
KIND:       Pod
VERSION:    v1

DESCRIPTION:
    Pod is a collection of containers that can run on a host. This resource is
    created by clients and scheduled onto hosts.
    
FIELDS:
  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    Standard object's metadata. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

  spec  <PodSpec>
    Specification of the desired behavior of the pod. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

  status        <PodStatus>
    Most recently observed status of the pod. This data may not be up to date.
    Populated by the system. Read-only. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

 

한 Pod에 있는 컨테이너들은 리소스를 공유하고 같은 Pod에 있는 컨테이너들은 내부 IP를 통해 통신한다.

 

1. get pods를 통해 pod 리스트를 확인할 수 있다.

@cloudshell:~ (proud-curve)$ kubectl get pods
NAME                                  READY   STATUS    RESTARTS   AGE
hello-world-rest-api-8c7449fd-f7lh2   1/1     Running   0          16h
@cloudshell:~ (proud-curve)$ kubectl get pods -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP          NODE                                                 NOMINATED NODE   READINESS GATES
hello-world-rest-api-8c7449fd-f7lh2   1/1     Running   0          16h   10.44.1.5   gke-in28minutes-cluster-default-pool-24f9f7fb-xq70   <none>           <none>

 

 

2. 특정 pod에 대해 상세 조회를 하려면 1번 단계에서 확인한 pod name을 이용해서 kubectl describe pod를 하면 된다.

@cloudshell:~ (proud-curve)$ kubectl describe pod hello-world-rest-api-8c7449fd-f7lh2
Name:             hello-world-rest-api-8c7449fd-f7lh2
Namespace:        default
Priority:         0
Service Account:  default
Node:             gke-in28minutes-cluster-default-pool-24f9f7fb-xq70/10.128.0.7
Start Time:       Sun, 16 Feb 2025 03:44:56 +0000
Labels:           app=hello-world-rest-api
                  pod-template-hash=8c7449fd
Annotations:      cloud.google.com/cluster_autoscaler_unhelpable_since: 2025-02-15T13:37:43+0000
                  cloud.google.com/cluster_autoscaler_unhelpable_until: Inf
Status:           Running
IP:               10.44.1.5
IPs:
  IP:           10.44.1.5
Controlled By:  ReplicaSet/hello-world-rest-api-8c7449fd
Containers:
  hello-world-rest-api:
    Container ID:   containerd://a5f84557e8c2e25fe5ba0e04bcabac8f9b77cbfbb491b98846169c71687f5c1e
    Image:          in28min/hello-world-rest-api:0.0.1.RELEASE
    Image ID:       docker.io/in28min/hello-world-rest-api@sha256:00469c343814aabe56ad1034427f546d43bafaaa11208a1eb0720993743f72be
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sun, 16 Feb 2025 03:45:15 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d2tdw (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       True 
  ContainersReady             True 
  PodScheduled                True 
Volumes:
  kube-api-access-d2tdw:
    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 op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:                      <none>

 

여기에서 Labels에 있는 이름이 중요하다. 나중에 리플리카셋이나 서비스 등으로 Pod을 묶을 때 쓰일 수 있다. 그리고 Annotation은 Pod에 대한 메타 정보이다.

 

 

 

Replicaset

리플리카셋은 Pod를 모니터링 하고 있다가 필요한 Pod 수보다 줄어들게 되면 다시 Pod를 생성한다. 특정 수 이상의 Pod이 실행되도록 만들어준다.

@cloudshell:~ (proud-curve)$ kubectl explain replicaset
GROUP:      apps
KIND:       ReplicaSet
VERSION:    v1

DESCRIPTION:
    ReplicaSet ensures that a specified number of pod replicas are running at
    any given time.
    
FIELDS:
  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    If the Labels of a ReplicaSet are empty, they are defaulted to be the same
    as the Pod(s) that the ReplicaSet manages. Standard object's metadata. More
    info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

  spec  <ReplicaSetSpec>
    Spec defines the specification of the desired behavior of the ReplicaSet.
    More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

  status        <ReplicaSetStatus>
    Status is the most recently observed status of the ReplicaSet. This data may
    be out of date by some window of time. Populated by the system. Read-only.
    More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

 

 

1. 리플리카셋 리스트를 여러 명령어로 조회할 수 있다.

@cloudshell:~ (proud-curve)$ kubectl get replicasets
NAME                            DESIRED   CURRENT   READY   AGE
hello-world-rest-api-8c7449fd   1         1         1       17h
@cloudshell:~ (proud-curve)$ kubectl get replicaset
NAME                            DESIRED   CURRENT   READY   AGE
hello-world-rest-api-8c7449fd   1         1         1       17h
@cloudshell:~ (proud-curve)$ kubectl get rs
NAME                            DESIRED   CURRENT   READY   AGE
hello-world-rest-api-8c7449fd   1         1         1       17h

 

 

2. Pod을 삭제하면 다른 이름으로 자동으로 Pod이 생성되는 것을 확인할 수 있는데, 이 역할을 하는 것이 Replicaset이라고 할 수 있다.

@cloudshell:~ (proud-curve)$ kubectl get pods
NAME                                  READY   STATUS    RESTARTS   AGE
hello-world-rest-api-8c7449fd-f7lh2   1/1     Running   0          17h
@cloudshell:~ (proud-curve)$ kubectl delete pod hello-world-rest-api-8c7449fd-f7lh2
pod "hello-world-rest-api-8c7449fd-f7lh2" deleted
@cloudshell:~ (proud-curve)$ kubectl get pods
NAME                                  READY   STATUS    RESTARTS   AGE
hello-world-rest-api-8c7449fd-bw2hn   1/1     Running   0          5s

 

 

3. pod을 3개로 늘려보자. 인스턴스가 3개로 늘어났다고 볼 수 있다.

@cloudshell:~ (proud-curve)$ kubectl scale deployment hello-world-rest-api --replicas=3
deployment.apps/hello-world-rest-api scaled
@cloudshell:~ (proud-curve)$ kubectl get pods
NAME                                  READY   STATUS              RESTARTS   AGE
hello-world-rest-api-8c7449fd-bw2hn   1/1     Running             0          5m47s
hello-world-rest-api-8c7449fd-fzg7d   0/1     ContainerCreating   0          4s
hello-world-rest-api-8c7449fd-mgg96   0/1     ContainerCreating   0          4s
@cloudshell:~ (proud-curve-451012-r7)$ kubectl get rs
NAME                            DESIRED   CURRENT   READY   AGE
hello-world-rest-api-8c7449fd   3         3         3       17h

 

 

4. Pod이 3개로 늘어나고 나서 hello-world 서비스를 브라우저로 접근하면 Pod가 돌아가면서 동작하여 서비스가 됨을 알 수 있다.

 

 

5. kubectl scale deployment를 통해 내부적으로 어떤 동작이 있었는지 보기 위해 event를 확인해보면 pod 2개가 추가로 생성된 것을 확인할 수 있다.

@cloudshell:~ (proud-curve)$ kubectl get events --sort-by=.metadata.creationTimestamp
LAST SEEN   TYPE     REASON              OBJECT                                     MESSAGE
17m         Normal   Scheduled           pod/hello-world-rest-api-8c7449fd-bw2hn    Successfully assigned default/hello-world-rest-api-8c7449fd-bw2hn to gke-in28minutes-cluster-default-pool-24f9f7fb-xq70
17m         Normal   Killing             pod/hello-world-rest-api-8c7449fd-f7lh2    Stopping container hello-world-rest-api
17m         Normal   SuccessfulCreate    replicaset/hello-world-rest-api-8c7449fd   Created pod: hello-world-rest-api-8c7449fd-bw2hn
17m         Normal   Pulled              pod/hello-world-rest-api-8c7449fd-bw2hn    Container image "in28min/hello-world-rest-api:0.0.1.RELEASE" already present on machine
17m         Normal   Created             pod/hello-world-rest-api-8c7449fd-bw2hn    Created container hello-world-rest-api
17m         Normal   Started             pod/hello-world-rest-api-8c7449fd-bw2hn    Started container hello-world-rest-api
12m         Normal   SuccessfulCreate    replicaset/hello-world-rest-api-8c7449fd   Created pod: hello-world-rest-api-8c7449fd-fzg7d
12m         Normal   ScalingReplicaSet   deployment/hello-world-rest-api            Scaled up replica set hello-world-rest-api-8c7449fd to 3 from 1
12m         Normal   Scheduled           pod/hello-world-rest-api-8c7449fd-fzg7d    Successfully assigned default/hello-world-rest-api-8c7449fd-fzg7d to gke-in28minutes-cluster-default-pool-24f9f7fb-vzdc
12m         Normal   Scheduled           pod/hello-world-rest-api-8c7449fd-mgg96    Successfully assigned default/hello-world-rest-api-8c7449fd-mgg96 to gke-in28minutes-cluster-default-pool-24f9f7fb-6q96
12m         Normal   SuccessfulCreate    replicaset/hello-world-rest-api-8c7449fd   Created pod: hello-world-rest-api-8c7449fd-mgg96
12m         Normal   Pulling             pod/hello-world-rest-api-8c7449fd-fzg7d    Pulling image "in28min/hello-world-rest-api:0.0.1.RELEASE"
12m         Normal   Pulling             pod/hello-world-rest-api-8c7449fd-mgg96    Pulling image "in28min/hello-world-rest-api:0.0.1.RELEASE"
12m         Normal   Created             pod/hello-world-rest-api-8c7449fd-fzg7d    Created container hello-world-rest-api
12m         Normal   Started             pod/hello-world-rest-api-8c7449fd-mgg96    Started container hello-world-rest-api
12m         Normal   Created             pod/hello-world-rest-api-8c7449fd-mgg96    Created container hello-world-rest-api
12m         Normal   Pulled              pod/hello-world-rest-api-8c7449fd-mgg96    Successfully pulled image "in28min/hello-world-rest-api:0.0.1.RELEASE" in 3.116s (3.116s including waiting). Image size: 88504325 bytes.
12m         Normal   Started             pod/hello-world-rest-api-8c7449fd-fzg7d    Started container hello-world-rest-api
12m         Normal   Pulled              pod/hello-world-rest-api-8c7449fd-fzg7d    Successfully pulled image "in28min/hello-world-rest-api:0.0.1.RELEASE" in 3.163s (3.163s including waiting). Image size: 88504325 bytes.

 

 

Deployment

다운타임 없이 새로운 버전을 배포할 수 있도록 Pod와 Replicaset의 배포를 관리한다.

@cloudshell:~ (proud-curve)$ kubectl explain deployment
GROUP:      apps
KIND:       Deployment
VERSION:    v1

DESCRIPTION:
    Deployment enables declarative updates for Pods and ReplicaSets.
    
FIELDS:
  apiVersion    <string>
    APIVersion defines the versioned schema of this representation of an object.
    Servers should convert recognized schemas to the latest internal value, and
    may reject unrecognized values. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

  kind  <string>
    Kind is a string value representing the REST resource this object
    represents. Servers may infer this from the endpoint the client submits
    requests to. Cannot be updated. In CamelCase. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

  metadata      <ObjectMeta>
    Standard object's metadata. More info:
    https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

  spec  <DeploymentSpec>
    Specification of the desired behavior of the Deployment.

  status        <DeploymentStatus>
    Most recently observed status of the Deployment.

 

 

1. 애플리케이션 도커 이미지를 변경한다.

@cloudshell:~ (proud-curve)$ kubectl get rs -o wide
NAME                            DESIRED   CURRENT   READY   AGE   CONTAINERS             IMAGES                                       SELECTOR
hello-world-rest-api-8c7449fd   3         3         3       17h   hello-world-rest-api   in28min/hello-world-rest-api:0.0.1.RELEASE   app=hello-world-rest-api,pod-template-hash=8c7449fd
@cloudshell:~ (proud-curve)$ kubectl set image deployment hello-world-rest-api hello-world-rest-api=in28min/hello-world-rest-api:0.0.2.RELEASE
deployment.apps/hello-world-rest-api image updated

 

 

2. 이미지 변경을 하게 되면 애플리케이션 버전2로 deployment 된 것인데, 이 과정에서 replicaset은 새로운 이름으로 생성이 되고 pod도 새 버전의 애플리케이션을 위한 pod이 구성된다.

@cloudshell:~ (proud-curve)$ kubectl get rs -o wide
NAME                             DESIRED   CURRENT   READY   AGE   CONTAINERS             IMAGES                                       SELECTOR
hello-world-rest-api-89b8d4c97   3         3         3       25s   hello-world-rest-api   in28min/hello-world-rest-api:0.0.2.RELEASE   app=hello-world-rest-api,pod-template-hash=89b8d4c97
hello-world-rest-api-8c7449fd    0         0         0       18h   hello-world-rest-api   in28min/hello-world-rest-api:0.0.1.RELEASE   app=hello-world-rest-api,pod-template-hash=8c7449fd
@cloudshell:~ (proud-curve)$ kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP          NODE                                                 NOMINATED NODE   READINESS GATES
hello-world-rest-api-89b8d4c97-6l564   1/1     Running   0          44s   10.44.1.9   gke-in28minutes-cluster-default-pool-24f9f7fb-xq70   <none>           <none>
hello-world-rest-api-89b8d4c97-6w9w5   1/1     Running   0          41s   10.44.2.8   gke-in28minutes-cluster-default-pool-24f9f7fb-6q96   <none>           <none>
hello-world-rest-api-89b8d4c97-m88z8   1/1     Running   0          39s   10.44.0.8   gke-in28minutes-cluster-default-pool-24f9f7fb-vzdc   <none>           <none>

 

 

3. 내부적으로 일어난 동작을 보면 새로운 relicaset을 먼저 생성한 후 pod 1개를 먼저 생성하여 image를 내려받아 컨테이너를 실행하고 기존 replicaset의 개수를 2로 줄이면서 기존 container를 중지하고 pod을 삭제한다. 이 작업을 replicas 개수만큼 3번만큼 진행하여 기존 relicaset에서 실행되던 pod을 순차적으로 신규 relicaset으로 이관되게 된다. 롤링 업데이트 전략이 적용된 예시이다.

@cloudshell:~ (proud-curve)$ kubectl get events --sort-by=.metadata.creationTimestamp
LAST SEEN   TYPE     REASON              OBJECT                                      MESSAGE
...
6m36s       Normal   SuccessfulCreate    replicaset/hello-world-rest-api-89b8d4c97   Created pod: hello-world-rest-api-89b8d4c97-6l564
6m35s       Normal   Scheduled           pod/hello-world-rest-api-89b8d4c97-6l564    Successfully assigned default/hello-world-rest-api-89b8d4c97-6l564 to gke-in28minutes-cluster-default-pool-24f9f7fb-xq70
6m36s       Normal   ScalingReplicaSet   deployment/hello-world-rest-api             Scaled up replica set hello-world-rest-api-89b8d4c97 to 1
6m35s       Normal   Pulling             pod/hello-world-rest-api-89b8d4c97-6l564    Pulling image "in28min/hello-world-rest-api:0.0.2.RELEASE"
6m34s       Normal   Started             pod/hello-world-rest-api-89b8d4c97-6l564    Started container hello-world-rest-api
6m34s       Normal   Created             pod/hello-world-rest-api-89b8d4c97-6l564    Created container hello-world-rest-api
6m34s       Normal   Pulled              pod/hello-world-rest-api-89b8d4c97-6l564    Successfully pulled image "in28min/hello-world-rest-api:0.0.2.RELEASE" in 1.45s (1.45s including waiting). Image size: 88504316 bytes.
6m33s       Normal   Pulling             pod/hello-world-rest-api-89b8d4c97-6w9w5    Pulling image "in28min/hello-world-rest-api:0.0.2.RELEASE"
6m33s       Normal   ScalingReplicaSet   deployment/hello-world-rest-api             Scaled down replica set hello-world-rest-api-8c7449fd to 2 from 3
6m33s       Normal   Killing             pod/hello-world-rest-api-8c7449fd-bw2hn     Stopping container hello-world-rest-api
6m33s       Normal   SuccessfulDelete    replicaset/hello-world-rest-api-8c7449fd    Deleted pod: hello-world-rest-api-8c7449fd-bw2hn
6m33s       Normal   Scheduled           pod/hello-world-rest-api-89b8d4c97-6w9w5    Successfully assigned default/hello-world-rest-api-89b8d4c97-6w9w5 to gke-in28minutes-cluster-default-pool-24f9f7fb-6q96
6m33s       Normal   ScalingReplicaSet   deployment/hello-world-rest-api             Scaled up replica set hello-world-rest-api-89b8d4c97 to 2 from 1
6m33s       Normal   SuccessfulCreate    replicaset/hello-world-rest-api-89b8d4c97   Created pod: hello-world-rest-api-89b8d4c97-6w9w5
6m32s       Normal   Started             pod/hello-world-rest-api-89b8d4c97-6w9w5    Started container hello-world-rest-api
6m32s       Normal   Created             pod/hello-world-rest-api-89b8d4c97-6w9w5    Created container hello-world-rest-api
6m32s       Normal   Pulled              pod/hello-world-rest-api-89b8d4c97-6w9w5    Successfully pulled image "in28min/hello-world-rest-api:0.0.2.RELEASE" in 879ms (879ms including waiting). Image size: 88504316 bytes.
6m31s       Normal   Scheduled           pod/hello-world-rest-api-89b8d4c97-m88z8    Successfully assigned default/hello-world-rest-api-89b8d4c97-m88z8 to gke-in28minutes-cluster-default-pool-24f9f7fb-vzdc
6m31s       Normal   Pulling             pod/hello-world-rest-api-89b8d4c97-m88z8    Pulling image "in28min/hello-world-rest-api:0.0.2.RELEASE"
6m31s       Normal   SuccessfulDelete    replicaset/hello-world-rest-api-8c7449fd    Deleted pod: hello-world-rest-api-8c7449fd-mgg96
6m31s       Normal   Killing             pod/hello-world-rest-api-8c7449fd-mgg96     Stopping container hello-world-rest-api
6m31s       Normal   SuccessfulCreate    replicaset/hello-world-rest-api-89b8d4c97   Created pod: hello-world-rest-api-89b8d4c97-m88z8
6m31s       Normal   ScalingReplicaSet   deployment/hello-world-rest-api             Scaled down replica set hello-world-rest-api-8c7449fd to 1 from 2
6m31s       Normal   ScalingReplicaSet   deployment/hello-world-rest-api             Scaled up replica set hello-world-rest-api-89b8d4c97 to 3 from 2
6m30s       Normal   Started             pod/hello-world-rest-api-89b8d4c97-m88z8    Started container hello-world-rest-api
6m30s       Normal   Pulled              pod/hello-world-rest-api-89b8d4c97-m88z8    Successfully pulled image "in28min/hello-world-rest-api:0.0.2.RELEASE" in 856ms (856ms including waiting). Image size: 88504316 bytes.
6m30s       Normal   Created             pod/hello-world-rest-api-89b8d4c97-m88z8    Created container hello-world-rest-api
6m29s       Normal   Killing             pod/hello-world-rest-api-8c7449fd-fzg7d     Stopping container hello-world-rest-api
6m29s       Normal   SuccessfulDelete    replicaset/hello-world-rest-api-8c7449fd    Deleted pod: hello-world-rest-api-8c7449fd-fzg7d
6m29s       Normal   ScalingReplicaSet   deployment/hello-world-rest-api             Scaled down replica set hello-world-rest-api-8c7449fd to 0 from 1

GKE 클러스터를 생성했다면, 이미 개발한 애플리케이션을 클러스터에 간단하게 배치하는 방법을 구글 클라우드 쉘을 이용하여 진행해보려고 한다.

GKE(구글 쿠버네티스 엔진) 클러스터 생성

Udemy의 'Spring Boot Java Microservices를 활용한 Kubernetes 초심자용 강의 - GKE, AWS, EKS, Azure AKS를 중심으로 다루기' 강의를 들으면서 이해하거나 기억해야 할 내용을 간략하게 정리한 것이다. 강의에 나온

lazytechlog.tistory.com

 
 
1. 클라우드 쉘을 통해 구글 쿠버네티스 클러스터에 연결한다. Clusters 메뉴에서 클러스터 이름을 클릭하고 들어가서, 오른쪽 상단의 Activate Cloud Shell을 클릭하면 하단에 클라우드 쉘이 뜬다. 처음 activate할 때는 약간의 로딩 시간이 걸린다.

GKE - Activate Cloud Shell

 
 
2. 하단에 뜬 터미널을 사용하기 편하게 다른 창으로 열어주는 것이 좋다. 하단의 터미널 오른쪽 상단에 있는 Open in new window 아이콘을 클릭한다. 새 창으로 터미널이 정상적으로 뜨면 하단의 터미널은 오른쪽 상단의 X 아이콘을 클릭하여 닫아준다.

Google Cloud Shell

 
 
3. 클라우드 쉘로 Cluster에 연결하기 위해서 클러스터 이름을 클릭 후 보이는 화면에서 상단에 있는 CONNECT 메뉴를 클릭한다. command line 오른쪽에 있는 복사 아이콘을 클릭하여 2번 단계에서 오픈한 새 창에 뜬 shell에 붙여넣기를 한다.
 
gcloud 명령어는 클러스터 이름과 zone, 그리고 project id를 명시하여 연결하도록 되어 있다.

GKE - Connect to the cluster

 
project id는 Google Cloud 오른쪽에 있는 프로젝트 이름을 클릭하면 뜨는 프로젝트 리스트 팝업창에서 확인할 수 있다.

 
 
4. 앞선 과정이 모두 선행되어 cloud shell에서 cluster에 연결이 된 상태여야 다음의 과정을 진행할 수 있다. 클라우드 쉘에서는 이미 설치되어 있는 kubectl 쿠버네티스 명령어를 사용하여 클라우드 클러스터와 상호작용할 수 있다. kubectl 버전을 확인해보자.

@cloudshell:~ (proud-curve)$ kubectl version
Client Version: v1.31.5
Kustomize Version: v5.4.2
Server Version: v1.31.5-gke.1023000

 
여기서 Server 버전은 연결되어 있는 클러스터 머신의 버전으로서 클러스터 생성 시 지정한 타겟 버전과 동일하다.
 
5. kubectl을 이용하여 이미 개발되어 있는 간단한 애플리케이션을 배포해보겠다. 애플리케이션은 docker hub에 있는 image(https://hub.docker.com/r/in28min/hello-world-rest-api/tags)를 이용하기 때문에 별도로 개발할 필요는 없다. image 이름과 버전을 지정하여 kubectl create deployment를 하면 배포가 된다.
 

kubectl create deployment hello-world-rest-api --image=in28min/hello-world-rest-api:0.0.1.RELEASE

 
 
6. 배포한 deployment를 외부 서비스로 노출한다.

kubectl expose deployment hello-world-rest-api --type=LoadBalancer --port=8080

 
 
7. 이제 이 서비스를 browser를 통해 확인할 수 있다. 외부 접속을 위한 정보를 확인하기 위해 Networking > Gateways, Services & Ingress 메뉴를 클릭한 후 오른쪽 페이지에서 SERVICES 탭을 클릭하면 서비스 리스트를 확인할 수 있다. Endpoints에 있는 URL로 배포한 애플리케이션에 접근할 수 있다.

GKE - Gateways, Services & Ingress

 
 
8. 7번 단계에서 확인한 {Endpoint}/hello-world-bean 주소를 browser에서 실행하면 간단한 hello world 메시지를 확인할 수 있다.

 

Udemy의 'Spring Boot Java Microservices를 활용한 Kubernetes 초심자용 강의 - GKE, AWS, EKS, Azure AKS를 중심으로 다루기' 강의를 들으면서 이해하거나 기억해야 할 내용을 간략하게 정리한 것이다. 강의에 나온 구글 클라우드 메뉴 위치나 구성이 달라서 현재 2025년 2월 시점에 강의를 들으면서 달라진 부분은 임의로 조정하면서 진행한 것임을 미리 밝힌다.

 

구글 클라우드 계정을 최초에 생성하면 My First Project가 자동 생성된다. 구글 클라우드 계정이 없다면, 다음의 글을 참고하여 진행한 이후 이후 단계를 따르면 된다.

 

구글 클라우드 무료 계정 생성

구글 계정으로 클라우드 계정 생성을 한 적이 없다면, 90일 동안 300 달러에 해당하는 크레딧으로 무료 사용이 가능하다. 1. 구글 계정이 없다면 가입하여 계정 생성을 한다. 이미 계정 생성이 되

lazytechlog.tistory.com

 

 

1. My First Project가 선택된 상태에서 상단의 조회 바에서 Kubernetes Engine을 찾아 선택한다.

 

 

2. Kubenetes Engine을 활성화 시키기 위해서는 Kubernetes Engine API > Enable을 클릭한다. 클릭 후 30초 정도 약간의 로딩 시간이 걸린다.

Google Kubenetes Engine API

 

 

3. Kubernetes Engine가 활성화 되면, Cluester 등 쿠버네티스 관련 메뉴가 보이고 오른쪽에 Cluster를 생성할 수 있는 화면이 오픈된다.

 

 

4. 2025년 2월 시점에는 default로 cluster가 Autopilot으로 되어 있고 권장하는 옵션이지만, 강의에서는 직접 노드를 설정하고 관리하는 Standard로 진행하여 cluster 모드를 Standard로 변경했다.

GKE Autopilot or Standard mode

 

 

5. Cluster 이름 입력하고, location을 선택하는데 기본 값은 Regional로 되어 있다. 앞서 언급한 것처럼 강의를 보면서 기억하면 좋을 내용을 기록하는 것이기 때문에 region으로 할지 zone으로 할지 선택할 때 강의와 동일하게 Zonal, us-central1-a로 선택했다. 보통은 자신과 물리적으로 가까운 아시아쪽으로 지정하는 것이 빠르다고 알고 있지만, location에 따라 서비스가 다르기 때문에 수강의 용의성을 위해 동일하게 진행했다.

Google Kubernetes cluster location

 

 

6. default pool 메뉴로 이동하여 Node 개수를 3인지 확인한다. default가 3으로 되어 있어 별도 수정없이 넘어갔다.

GKE default pool

 

 

7. Machine 타입이 default로 E2로 되어 있는데 강의대로 N1으로 변경하여 진행한다. 이 옵션을 변경하면 vCPU와 Memory 옵션이 바뀐다.

GKE Machine configuration

 

 

8. 아래쪽으로 내려가면 Boot disk size가 default로 100GB로 되어 있다. 이 상태로 그대로 Create 버튼을 클릭하여 Cluster를 생성한다.

 

 

9. 클러스터 생성이 정상적으로 된다면 약 5분 정도의 시간이 걸린다. 그런데 처음 8번 단계까지 진행하고 생성 버튼을 클릭했을 때 SSD 용량이 충분치 않다고 에러 메시지가 뜨면서 정상적으로 처리되지 않았다. 이 region에 디스크 용량이 250GB까지만 가능한 것으로 보여 다른 zone이나 region으로 변경을 시도해봤으나, 다 실패해서 아래의 10번 단계처럼 디스크 사이즈를 줄여서 시도했다.

Insufficient regional quota to satisfy request: resource "SSD_TOTAL_GB": request requires '300.0' and is short '50.0'. project has a quota of '250.0' with '250.0' available. View and manage quotas at https://console.cloud.google.com/iam-admin/quotas?usage=USED&project=XXXX

 

 

10. Boot disk size를 80GB로 조정했다. 노드가 3개이므로 총 250GB 내로 되게 하려면 가능한 최대 숫자라고 생각했다. 이 값으로 조정 후 정상적으로 Cluster 생성이 되었다. 약 5분 정도 걸린다.

GKE Boot disk size

 

 

11. 성공적으로 생성이 되었다면, Clusters 메뉴를 클릭하면 오른쪽 하단에서 클러스터 이름과 Status가 정상 상태로 확인이 된다. 입력한 것처럼 node 개수는 3, Location과 Tier도 각각 선택한 것과 동일한지 확인할 수 있다. 이름을 클릭하여 상세 정보를 볼 수도 있다.

GKE Clusters

 

 

+ Recent posts