애플리케이션 배포

이 문서에서는 베어메탈용 GKE에서 애플리케이션을 배포하는 방법을 설명합니다.

시작하기 전에

워크로드를 배포하려면 워크로드를 실행할 수 있는 사용자, 하이브리드, 독립형 클러스터가 있어야 합니다.

배포 만들기

다음 단계에서는 클러스터에 배포를 만듭니다.

  1. 다음 매니페스트를 my-deployment.yaml이라는 파일에 복사합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-deployment
    spec:
      selector:
        matchLabels:
          app: metrics
          department: sales
      replicas: 3
      template:
        metadata:
          labels:
            app: metrics
            department: sales
        spec:
          containers:
          - name: hello
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
    
  2. kubectl apply를 사용하여 배포를 만듭니다.

    kubectl apply -f my-deployment.yaml --kubeconfig CLUSTER_KUBECONFIG
    

    CLUSTER_KUBECONFIG를 클러스터의 kubeconfig 파일 경로로 바꿉니다.

  3. 성공적으로 생성되었는지 확인하기 위해 배포에 대한 기본 정보를 확인합니다.

    kubectl get deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    출력은 배포에 사용 가능한 pod가 3개 있음을 보여줍니다.

    NAME            READY   UP-TO-DATE   AVAILABLE   AGE
    my-deployment   3/3     3            3           27s
    
  4. 배포에서 포드가 나열됩니다.

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG
    

    출력은 배포에 3개의 포드가 실행 중임을 보여줍니다.

    NAME                             READY   STATUS    RESTARTS   AGE
    my-deployment-869f65669b-5259x   1/1     Running   0          34s
    my-deployment-869f65669b-9xfrs   1/1     Running   0          34s
    my-deployment-869f65669b-wn4ft   1/1     Running   0          34s
    
  5. 배포에 대한 자세한 정보를 확인하세요.

    kubectl get deployment my-deployment --output yaml --kubeconfig CLUSTER_KUBECONFIG
    

    출력은 배포 사양 및 상태에 대한 세부정보를 보여줍니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      ...
      generation: 1
      name: my-deployment
      namespace: default
      ...
    spec:
      ...
      replicas: 3
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: metrics
          department: sales
      ...
        spec:
          containers:
          - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
            imagePullPolicy: IfNotPresent
            name: hello
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
          dnsPolicy: ClusterFirst
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
    status:
      availableReplicas: 3
      conditions:
      - lastTransitionTime: "2023-06-29T16:17:17Z"
        lastUpdateTime: "2023-06-29T16:17:17Z"
        message: Deployment has minimum availability.
        reason: MinimumReplicasAvailable
        status: "True"
        type: Available
      - lastTransitionTime: "2023-06-29T16:17:12Z"
        lastUpdateTime: "2023-06-29T16:17:17Z"
        message: ReplicaSet "my-deployment-869f65669b" has successfully progressed.
        reason: NewReplicaSetAvailable
        status: "True"
        type: Progressing
      observedGeneration: 1
      readyReplicas: 3
      replicas: 3
      updatedReplicas: 3
    
  6. 배포를 설명합니다.

    kubectl describe deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    출력은 연결된 ReplicaSet을 포함하여 배포에 대한 잘 정돈된 세부정보를 보여줍니다.

    Name:                   my-deployment
    Namespace:              default
    CreationTimestamp:      Thu, 29 Jun 2023 16:17:12 +0000
    Labels:                 <none>
    Annotations:            deployment.kubernetes.io/revision: 1
    Selector:               app=metrics,department=sales
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=metrics
              department=sales
      Containers:
      hello:
        Image:        us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
        Port:         <none>
        Host Port:    <none>
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   my-deployment-869f65669b (3/3 replicas created)
    Events:
      Type    Reason             Age    From                   Message
      ----    ------             ----   ----                   -------
      Normal  ScalingReplicaSet  6m50s  deployment-controller  Scaled up replica set my-deployment-869f65669b to 3
    

LoadBalancer 유형의 서비스 만들기

클러스터 외부의 클라이언트에 배포를 노출하는 한 가지 방법은 LoadBalancer 유형의 Kubernetes 서비스를 만드는 것입니다.

LoadBalancer 유형의 서비스를 만들려면 다음 안내를 따르세요.

  1. 다음 매니페스트를 my-service.yaml이라는 파일에 복사합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: metrics
        department: sales
      type: LoadBalancer
      ports:
      - port: 80
        targetPort: 8080
    

    이 연습에서 서비스에 대해 꼭 알아야 할 점은 다음과 같습니다.

    • app: metrics 라벨과 department: sales 라벨이 모두 있는 Pod는 서비스의 구성원입니다. my-deployment의 포드에 이러한 라벨이 있습니다.

    • 클라이언트가 TCP 포트 80에서 서비스로 요청을 보내면 TCP 포트 8080의 구성원 포드로 요청이 전달됩니다.

    • 모든 구성원 포드에는 TCP 포트 8080에서 리슨하는 컨테이너가 있어야 합니다.

    기본적으로 hello-app 컨테이너는 TCP 포트 8080에서 리슨합니다. 앱의 Dockerfile 및 소스 코드를 보면 이 포트 설정을 확인할 수 있습니다.

  2. kubectl apply를 사용해서 클러스터에 서비스를 만듭니다.

    kubectl apply -f my-service.yaml --kubeconfig CLUSTER_KUBECONFIG
    

    CLUSTER_KUBECONFIG를 클러스터의 kubeconfig 파일 경로로 바꿉니다.

  3. 서비스를 확인합니다.

    kubectl get service my-service --output yaml --kubeconfig CLUSTER_KUBECONFIG
    

    출력은 다음과 비슷합니다.

    apiVersion: v1
    kind: Service
    metadata:
      ...
      name: my-service
      namespace: default
      ...
    spec:
      allocateLoadBalancerNodePorts: true
      clusterIP: 10.96.2.165
      clusterIPs:
      - 10.96.2.165
      externalTrafficPolicy: Cluster
      internalTrafficPolicy: Cluster
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - nodePort: 31565
        port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: metrics
        department: sales
      sessionAffinity: None
      type: LoadBalancer
    status:
      loadBalancer:
        ingress:
        - ip: 192.168.1.13
    

    앞의 출력에서 서비스에 clusterIP와 외부 IP 주소가 있는 것을 확인할 수 있습니다. 또한 nodePort, port, targetPort도 가졌습니다.

    clusterIP는 이 연습과 관련이 없습니다. 외부 IP 주소(status.loadBalancer.ingress.ip)는 클러스터 구성 파일에서 부하 분산기 주소 풀(spec.loadBalancer.addressPools)을 정의할 때 지정한 주소 범위에 포함됩니다.

    예를 들어 서비스의 이전 출력에 표시된 값을 보겠습니다.

    • 외부 IP 주소: 192.168.1.13
    • port: 80
    • nodePort: 31565
    • targetPort: 8080

    클라이언트가 TCP 포트 80192.168.1.13으로 요청을 전송합니다. 요청은 부하 분산기로 라우팅되고 여기에서 TCP 포트 8080의 구성원 포드로 전달됩니다.

  4. 서비스를 호출합니다.

    curl INGRESS_IP_ADDRESS
    

    INGRESS_IP_ADDRESS를 이전 단계에서 검색한 서비스의 status 섹션에 있는 인그레스 IP 주소로 바꿉니다(status.loadBalancer.ingress).

    출력에 Hello, world! 메시지가 표시됩니다.

    Hello, world!
    Version: 2.0.0
    Hostname: my-deployment-869f65669b-wn4ft
    

LoadBalancer 포트 한도

LoadBalancer 유형은 NodePort 유형의 확장입니다. 따라서 LoadBalancer 유형의 서비스에 클러스터 IP 주소 및 하나 이상의 nodePort 값이 포함됩니다. 기본적으로 Kubernetes는 노드 포트를 LoadBalancer 유형의 서비스에 할당합니다. 이러한 할당은 클러스터에 할당된 2,768개의 사용 가능한 노드 포트를 빠르게 소진할 수 있습니다. 노드 포트를 저장하려면 LoadBalancer 서비스 사양에서 allocateLoadBalancerNodePorts 필드를 false로 설정하여 부하 분산기 노드 포트 할당을 사용 중지합니다. 이렇게 설정하면 Kubernetes가 LoadBalancer 서비스에 노드 포트를 할당할 수 없습니다. 자세한 내용은 Kubernetes 문서의 부하 분산기 NodePort 할당 중지를 참조하세요.

다음은 노드 포트를 사용하지 않는 서비스를 만들기 위한 매니페스트입니다.

apiVersion: v1
kind: Service
metadata:
  name: service-does-not-use-nodeports
spec:
  selector:
    app: my-app
  type: LoadBalancer
  ports:
  - port: 8000
  # Set allocateLoadBalancerNodePorts to false
  allocateLoadBalancerNodePorts: false

서비스 삭제

서비스를 삭제하려면 다음 안내를 따르세요.

  1. kubectl delete를 사용해서 클러스터에서 서비스를 삭제합니다.

    kubectl delete service my-service --kubeconfig CLUSTER_KUBECONFIG
    
  2. 서비스가 삭제되었는지 확인합니다.

    kubectl get services --kubeconfig CLUSTER_KUBECONFIG
    

    출력에 my-service가 더 이상 표시되지 않습니다.

배포 삭제

배포를 삭제하려면 다음 안내를 따르세요.

  1. kubectl delete를 사용해서 클러스터에서 배포를 삭제합니다.

    kubectl delete deployment my-deployment --kubeconfig CLUSTER_KUBECONFIG
    

    배포가 삭제되었는지 확인합니다.

    kubectl get deployments --kubeconfig CLUSTER_KUBECONFIG
    

    출력에 my-deployment가 더 이상 표시되지 않습니다.

다음 단계

서비스 및 인그레스 만들기