애플리케이션 배포

이 문서에서는 VMware용 Anthos 클러스터(GKE On-Prem)의 사용자 클러스터에 애플리케이션을 배포하는 방법을 설명합니다.

시작하기 전에

사용자 클러스터를 만듭니다(빠른 시작 | 전체 안내).

관리 워크스테이션에 SSH를 통해 연결

관리자 워크스테이션에 SSH를 통해 연결합니다.

ssh -i ~/.ssh/vsphere_workstation ubuntu@[IP_ADDRESS]

여기서 [IP_ADDRESS]는 관리자 워크스테이션의 IP 주소입니다.

관리 워크스테이션에서 이 주제의 남은 단계를 모두 수행합니다.

배포 만들기

배포 매니페스트는 다음과 같습니다.

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"

my-deployment.yaml 파일에 매니페스트를 복사하고 배포를 만듭니다.

kubectl apply --kubeconfig [USER_CLUSTER_KUBECONFIG] -f my-deployment.yaml

여기서 [USER_CLUSTER_KUBECONFIG]는 사용자 클러스터의 kubeconfig 파일 경로입니다.

배포에 대한 기본 정보를 가져옵니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] get deployment my-deployment

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

NAME            READY   UP-TO-DATE   AVAILABLE   AGE
my-deployment   3/3     3            3           27s

배포에서 pod가 나열됩니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] get pods

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

NAME                             READY   STATUS    RESTARTS   AGE
my-deployment-54944c8d55-4srm2   1/1     Running   0          6s
my-deployment-54944c8d55-7z5nn   1/1     Running   0          6s
my-deployment-54944c8d55-j62n9   1/1     Running   0          6s

배포에 대한 자세한 정보를 확인하세요.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] get deployment my-deployment --output yaml

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

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: "2019-11-11T18:44:02Z"
    lastUpdateTime: "2019-11-11T18:44:02Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: "2019-11-11T18:43:58Z"
    lastUpdateTime: "2019-11-11T18:44:02Z"
    message: ReplicaSet "my-deployment-54944c8d55" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 1
  readyReplicas: 3
  replicas: 3
  updatedReplicas: 3

배포를 설명합니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] describe deployment my-deployment

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

Name:                   my-deployment
Namespace:              default
CreationTimestamp:      Mon, 11 Nov 2019 10:43:58 -0800
Labels:                 
...
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:         
    Host Port:    
    Environment:  
    Mounts:       
  Volumes:        
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  
NewReplicaSet:   my-deployment-54944c8d55 (3/3 replicas created)

LoadBalancer 유형의 서비스 만들기

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

LoadBalancer 유형 서비스의 매니페스트는 다음과 같습니다.

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

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

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

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

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

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

[SERVICE_IP_ADDRESS]를 소유하고 있지만 아직 사용하지 않은 주소로 바꿉니다. 예를 들어 회사가 소유한 공개 IP 주소로 설정할 수 있습니다. 또는 회사 네트워크의 비공개 주소로 설정할 수도 있습니다.

선택한 주소는 서비스에 요청을 보내는 모든 클라이언트의 위치에서 라우팅할 수 있어야 합니다. 예를 들어 비공개 주소를 선택하면 외부 클라이언트가 서비스에 요청을 보낼 수 없습니다.

my-service.yaml 파일에 매니페스트를 저장하고 서비스를 만듭니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] apply -f my-service.yaml

여기서 [USER_CLUSTER_KUBECONFIG]는 사용자 클러스터의 kubeconfig 파일 경로입니다.

서비스를 만들면 Anthos clusters on VMware는 F5 BIG-IP 부하 분산기에서 loadBalancerIP 주소를 자동으로 구성합니다.

서비스를 확인합니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] get service my-service --output yaml

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

apiVersion: v1
kind: Service
metadata:
  ...
  name: my-service
  namespace: default
  ...
spec:
  clusterIP: 10.107.84.202
  externalTrafficPolicy: Cluster
  loadBalancerIP: 203.0.113.1
  ports:
  - nodePort: 31919
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: metrics
    department: sales
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.1

앞의 출력에서 서비스가 clusterIPloadBalancerIP를 가졌음을 알 수 있습니다. 또한 nodePort, port, targetPort도 가졌습니다.

clusterIP는 이 실습과 관련이 없습니다. loadBalancerIPmy-service.yaml에 제공한 IP 주소입니다.

예를 들어 이전 출력에 표시된 값을 보겠습니다. 서비스가 loadBalancerIP = 203.0.113.1, port = 80, nodePort = 31919, targetPort = 8080을 가졌다고 가정해 봅니다.

클라이언트가 TCP 포트 80의 203.0.113.1로 요청을 전송합니다. 요청은 F5 BIG-IP 부하 분산기로 라우팅됩니다. 부하 분산기는 사용자 클러스터 노드 중 하나를 선택하고 요청을 TCP 포트 3191의 [NODE_ADDRESS]로 전달합니다. 노드의 iptables 규칙은 요청을 TCP 포트 8080의 구성원 pod로 전달합니다.

서비스를 호출합니다.

curl [SERVICE_IP_ADDRESS]

여기서 [SERVICE_IP_ADDRESS]loadBalancerIP에 지정한 주소입니다.

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

curl 21.0.133.48
Hello, world!
Version: 2.0.0
Hostname: my-deployment-dbd86c8c4-9wpbv

서비스 삭제

서비스를 삭제합니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] delete service my-service

서비스가 삭제되었는지 확인합니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] get services

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

배포 삭제

배포를 삭제합니다.

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] delete deployment my-deployment

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

kubectl --kubeconfig [USER_CLUSTER_KUBECONFIG] get deployments

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

다음 단계

서비스 및 인그레스 만들기