컨테이너화된 웹 서버 앱 배포


이 튜토리얼에서는 오프라인 Google Distributed Cloud (GDC) 오프라인 환경에서 컨테이너 애플리케이션을 업로드하고 Kubernetes 클러스터에서 해당 애플리케이션을 실행하는 방법을 설명합니다. 컨테이너화된 워크로드는 프로젝트 네임스페이스 내의 Kubernetes 클러스터에서 실행됩니다. 클러스터는 서로 다른 장애 도메인과 격리 보장을 제공하기 위해 프로젝트와 서로 논리적으로 분리되어 있습니다. 하지만 컨테이너화된 워크로드를 프로젝트 내에서 관리할 수 있도록 클러스터가 프로젝트에 연결되어 있어야 합니다.

컨테이너 앱을 배포할 때 가장 큰 장애물 중 하나는 앱의 바이너리를 오프라인 데이터 센터로 가져오는 것입니다. 인프라팀 및 관리자와 협력하여 애플리케이션을 워크스테이션으로 전송하거나 지속적 통합 및 지속적 배포(CI/CD) 서버에서 이 튜토리얼을 직접 구현합니다.

이 튜토리얼에서는 Google CloudArtifact Registry에서 제공되는 샘플 웹 서버 앱을 사용합니다.

목표

  • 관리형 Harbor 레지스트리를 만듭니다.
  • 관리형 Harbor 레지스트리로 컨테이너 이미지를 푸시합니다.
  • Kubernetes 클러스터 만들기
  • 샘플 컨테이너 앱을 클러스터에 배포합니다.

비용

GDC는 에어 갭 데이터 센터에서 실행되도록 설계되었으므로 결제 프로세스와 정보는 GDC 배포에만 국한되며 다른 Google 제품에서 관리하지 않습니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.

예상 비용 대시보드를 사용하여 인보이스의 향후 SKU 비용을 예측하세요.

스토리지 및 컴퓨팅 사용량을 추적하려면 결제 사용량 대시보드를 사용하세요.

시작하기 전에

  1. 컨테이너화된 배포를 관리할 프로젝트가 있는지 확인합니다. 프로젝트가 없으면 프로젝트를 만듭니다.

  2. 프로젝트 네임스페이스를 환경 변수로 설정합니다.

    export NAMESPACE=PROJECT_NAMESPACE
    
  3. gdcloud CLI를 다운로드하고 설치합니다.

  4. 조직 IAM 관리자에게 다음 역할을 부여해 달라고 요청하세요.

    • 프로젝트 네임스페이스의 네임스페이스 관리자 역할 (namepspace-admin) 이 역할은 프로젝트에서 컨테이너 워크로드를 배포하는 데 필요합니다.

    • 프로젝트 네임스페이스의 Harbor 인스턴스 관리자 역할 (harbor-instance-admin) 이 역할은 모든 Harbor 리소스에 대한 읽기 및 쓰기 액세스 권한에 필요합니다. Harbor 인스턴스를 삭제하는 데도 필요합니다.

    • 프로젝트 네임스페이스의 Harbor 인스턴스 뷰어 역할 (harbor-instance-viewer) 이 역할은 Harbor 인스턴스를 보고 선택하는 데 필요합니다.

    • 프로젝트 네임스페이스의 Harbor 프로젝트 생성자 역할 (harbor-project-creator) Harbor 프로젝트에 액세스하고 이를 관리하는 데 필요한 역할입니다.

    • 사용자 클러스터 관리자 역할 (user-cluster-admin): 이 역할은 Kubernetes 클러스터를 만드는 데 필요하며 네임스페이스에 바인딩되지 않습니다.

  5. 영역 관리 API 서버에 로그인하고 사용자 ID로 kubeconfig 파일을 생성합니다. kubeconfig 경로를 환경 변수로 설정합니다.

    export MANAGEMENT_API_SERVER=MANAGEMENT_API_SERVER_KUBECONFIG_PATH
    

관리형 Harbor 레지스트리 만들기

GDC 에어갭은 Harbor를 사용하여 컨테이너 이미지를 저장하고 관리할 수 있는 완전 관리형 서비스인 Harbor as a Service를 제공합니다.

Harbor를 서비스로 사용하려면 먼저 Harbor 레지스트리 인스턴스와 Harbor 프로젝트를 만들어야 합니다.

Harbor 레지스트리 인스턴스 만들기

Harbor 컨테이너 레지스트리 인스턴스를 만들려면 다음 단계를 완료하세요.

콘솔

  1. 탐색 메뉴의 CI/CD 섹션에서 Harbor Container Registry를 선택합니다.

  2. Harbor 인스턴스를 만들 영역을 선택합니다. Harbor 인스턴스는 영역별 리소스이며 고가용성을 보장하려면 각 영역에서 수동으로 만들어야 합니다.

  3. 인스턴스 만들기를 클릭합니다.

  4. 인스턴스 이름을 입력하고 Harbor 관리 서비스 약관에 동의합니다.

  5. 인스턴스 만들기를 클릭합니다.

  6. Harbor 인스턴스 섹션에 새 Harbor 인스턴스가 있는지 확인합니다.

  7. Harbor 인스턴스로 이동 외부 링크를 클릭하고 인스턴스 URL을 확인합니다. 예를 들어 인스턴스 URL 형식은 harbor-1.org-1.zone1.google.gdc.test와 유사합니다. 인스턴스 URL에 https:// 접두사가 포함되면 안 됩니다.

  8. 나중에 튜토리얼에서 사용할 인스턴스 URL을 변수로 설정합니다.

    export INSTANCE_URL=INSTANCE_URL
    

    INSTANCE_URL을 Harbor 레지스트리 인스턴스의 URL로 바꿉니다.

    예를 들면 다음과 같습니다.

    export INSTANCE_URL=harbor-1.org-1.zone1.google.gdc.test
    

gdcloud

  1. 새 Harbor 컨테이너 레지스트리 인스턴스를 만듭니다.

    gdcloud harbor instances create INSTANCE_NAME \
        --project=PROJECT \
    

    다음을 바꿉니다.

    • INSTANCE_NAME: Harbor 인스턴스의 이름입니다.
    • PROJECT: GDC 프로젝트의 이름입니다.
  2. 인스턴스의 URL을 나열합니다.

    gdcloud harbor instances describe INSTANCE_NAME \
        --project=PROJECT
    

    결과는 다음과 유사합니다.

    # Several lines of code are omitted here.
    status:
      url: https://harbor-1.org-1.zone1.google.gdc.test
    
  3. 나중에 튜토리얼에서 사용할 인스턴스 URL을 변수로 설정합니다.

    export INSTANCE_URL=INSTANCE_URL
    

    INSTANCE_URL을 Harbor 레지스트리 인스턴스의 URL로 바꿉니다. 인스턴스 URL에 https:// 접두사가 포함되지 않아야 합니다.

    예를 들면 다음과 같습니다.

    export INSTANCE_URL=harbor-1.org-1.zone1.google.gdc.test
    

레지스트리에서 Harbor 프로젝트 만들기

컨테이너 이미지를 관리하려면 Harbor 레지스트리 인스턴스 내에 Harbor 프로젝트를 만들어야 합니다.

콘솔

  1. Harbor Container Registry 페이지에서 Create A Harbor Project를 클릭합니다.

  2. 프로젝트 이름을 입력합니다.

  3. 만들기를 클릭합니다.

  4. 나중에 튜토리얼에서 사용할 Harbor 프로젝트 이름을 변수로 설정합니다.

    export HARBOR_PROJECT=HARBOR_PROJECT
    

gdcloud

  1. 새 Harbor 프로젝트를 만듭니다.

    gdcloud harbor harbor-projects create HARBOR_PROJECT \
        --project=PROJECT \
        --instance=INSTANCE_NAME
    

    다음을 바꿉니다.

    • HARBOR_PROJECT: 만들 Harbor 프로젝트의 이름입니다.
    • PROJECT: GDC 프로젝트의 이름입니다.
    • INSTANCE_NAME: Harbor 인스턴스의 이름입니다.
  2. 나중에 튜토리얼에서 사용할 Harbor 프로젝트 이름을 변수로 설정합니다.

    export HARBOR_PROJECT=HARBOR_PROJECT
    

Docker 구성

Harbor 레지스트리에서 Docker를 사용하려면 다음 단계를 완료하세요.

  1. Harbor를 서비스로 신뢰하도록 Docker를 구성합니다. 자세한 내용은 Harbor 루트 CA를 신뢰하도록 Docker 구성을 참고하세요.

  2. Harbor에 대한 Docker 인증을 구성합니다. 자세한 내용은 Harbor 레지스트리 인스턴스에 Docker 인증 구성을 참고하세요.

Kubernetes 이미지 풀 보안 비밀 만들기

비공개 Harbor 프로젝트를 사용하므로 Kubernetes 이미지 가져오기 보안 비밀을 만들어야 합니다.

  1. 서비스 계정으로 사용할 Harbor 프로젝트 로봇 계정을 추가합니다.

    1. Harbor 콘솔에서 Harbor 프로젝트를 선택합니다.

    2. 로봇 계정을 클릭합니다.

    3. New Robot Account(새 로봇 계정)를 선택합니다.

    4. 새 로봇 계정의 이름을 지정하고 추가 설정을 정의합니다.

    5. 추가를 클릭합니다.

    6. 성공 화면에 로봇 계정 이름과 보안 비밀이 표시됩니다. 다음 단계에서 참고할 수 있도록 이 화면을 열어 두세요.

    자세한 내용은 Harbor 문서를 참고하세요(https://goharbor.io/docs/2.8.0/working-with-projects/project-configuration/create-robot-accounts/#add-a-robot-account).

  2. 새 터미널 창에서 Harbor 프로젝트 로봇 계정과 보안 토큰으로 Docker에 로그인합니다.

    docker login ${INSTANCE_URL}
    

    메시지가 표시되면 Harbor 콘솔 성공 화면에서 이전 단계에 제공된 사용자 이름의 로봇 프로젝트 이름과 비밀번호의 비밀 토큰을 삽입합니다.

  3. 이미지 가져오기 보안 비밀의 임의 이름을 설정합니다.

    export SECRET=SECRET
    
  4. 이미지 풀에 필요한 보안 비밀을 만듭니다.

    kubectl create secret docker-registry ${SECRET}  \
        --from-file=.dockerconfigjson=DOCKER_CONFIG \
        -n ${NAMESPACE}
    

    DOCKER_CONFIG.docker/config.json 파일의 경로로 바꿉니다.

  5. GDC 프로젝트 네임스페이스에 보안 비밀이 있는지 확인합니다.

    kubectl get secrets -n ${NAMESPACE}
    

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

    NAME          TYPE                               DATA     AGE
    my-secret     kubernetes.io/dockerconfigjson     1        23s
    

관리형 Harbor 레지스트리에 컨테이너 이미지 푸시

이 튜토리얼에서는 nginx 웹 서버 이미지를 다운로드하여 관리형 Harbor 레지스트리에 푸시하고 이를 사용하여 샘플 nginx 웹 서버 앱을 Kubernetes 클러스터에 배포합니다. nginx 웹 서버 앱은 공개 Docker Hub 저장소에서 사용할 수 있습니다.

  1. 외부 네트워크를 사용하여 Docker Hub에서 로컬 워크스테이션으로 nginx 이미지를 가져옵니다.

    docker pull nginx
    
  2. 저장소 이름으로 로컬 이미지에 태그를 지정합니다.

    docker tag nginx ${INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.25
    
  3. nginx 컨테이너 이미지를 관리형 Harbor 레지스트리로 푸시합니다.

    docker push ${INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.25
    

Kubernetes 클러스터 만들기

이제 관리형 Harbor 레지스트리에 nginx 컨테이너 이미지가 저장되어 액세스할 수 있으므로 nginx 웹 서버를 실행할 Kubernetes 클러스터를 만듭니다.

콘솔

  1. 탐색 메뉴에서 Kubernetes Engine > 클러스터를 선택합니다.

  2. 클러스터 만들기를 클릭합니다.

  3. 이름 필드에 클러스터 이름을 지정합니다.

  4. Kubernetes 클러스터를 만들 영역을 선택합니다. Kubernetes 클러스터는 영역 리소스이므로 고가용성을 보장하려면 각 영역에서 수동으로 만들어야 합니다.

  5. 프로젝트 연결을 클릭하고 클러스터에 연결할 프로젝트를 선택합니다. 그런 다음 저장을 클릭하고

  6. 만들기를 클릭합니다.

  7. 클러스터가 생성될 때까지 기다립니다. 클러스터를 사용할 수 있게 되면 클러스터 이름 옆에 상태 READY가 표시됩니다.

API

  1. Cluster 커스텀 리소스를 만들고 cluster.yaml과 같은 YAML 파일로 저장합니다.

    apiVersion: cluster.gdc.goog/v1
    kind: Cluster
    metadata:
      name: CLUSTER_NAME
      namespace: platform
    

    CLUSTER_NAME 값을 클러스터 이름으로 바꿉니다.

  2. 커스텀 리소스를 GDC 인스턴스에 적용합니다.

    kubectl create -f cluster.yaml --kubeconfig ${MANAGEMENT_API_SERVER}
    
  3. GDC 콘솔을 사용하여 프로젝트를 Kubernetes 클러스터에 연결합니다. 현재 API를 사용하여 클러스터에 프로젝트를 연결할 수 없습니다.

Kubernetes 클러스터 만들기에 대한 자세한 내용은 Kubernetes 클러스터 만들기를 참고하세요.

샘플 컨테이너 앱 배포

이제 nginx 컨테이너 이미지를 Kubernetes 클러스터에 배포할 준비가 되었습니다.

Kubernetes는 애플리케이션을 하나 이상의 컨테이너를 포함하는 확장 가능한 단위인 Pod 리소스로 나타냅니다. 포드는 Kubernetes에서 배포 가능한 최소 단위입니다. 일반적으로 포드를 클러스터 전체에 걸쳐 함께 확장하고 배포할 수 있는 복제본 집합으로 배포합니다. 복제본 세트를 배포하는 한 가지 방법은 Kubernetes Deployment를 사용하는 것입니다.

이 섹션에서는 클러스터에서 nginx 컨테이너 앱을 실행하기 위해 Kubernetes Deployment을 만듭니다. 이 배포에는 복제본 또는 포드가 있습니다. 하나의 Deployment 포드에는 하나의 컨테이너(nginx 컨테이너 이미지)만 포함됩니다. 또한 클라이언트가 Deployment의 포드로 요청을 보내는 안정적인 방법을 제공하는 Service 리소스를 만듭니다.

Kubernetes 클러스터에 nginx 웹 서버를 배포합니다.

  1. Kubernetes 클러스터에 로그인하고 사용자 ID로 kubeconfig 파일을 생성합니다. kubeconfig 경로를 환경 변수로 설정합니다.

    export KUBECONFIG=CLUSTER_KUBECONFIG_PATH
    
  2. Kubernetes DeploymentService 커스텀 리소스를 만들고 배포합니다.

    kubectl --kubeconfig ${KUBECONFIG} -n ${NAMESPACE} \
    create -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: ${INSTANCE_URL}/${HARBOR_PROJECT}/nginx:1.25
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: ${SECRET}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      selector:
        app: nginx
      ports:
        - port: 80
          protocol: TCP
      type: LoadBalancer
    EOF
    
  3. 포드가 배포에 의해 생성되었는지 확인합니다.

    kubectl get pods -l app=nginx -n ${NAMESPACE}
    

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

    NAME                                READY     STATUS    RESTARTS   AGE
    nginx-deployment-1882529037-6p4mt   1/1       Running   0          1h
    nginx-deployment-1882529037-p29za   1/1       Running   0          1h
    nginx-deployment-1882529037-s0cmt   1/1       Running   0          1h
    
  4. 네임스페이스로의 모든 네트워크 트래픽을 허용하는 네트워크 정책을 만듭니다.

    kubectl --kubeconfig ${KUBECONFIG} -n ${NAMESPACE} \
    create -f - <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      annotations:
      name: allow-all
    spec:
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      podSelector: {}
      policyTypes:
      - Ingress
    EOF
    
  5. nginx 서비스의 IP 주소를 내보냅니다.

      export IP=`kubectl --kubeconfig=${KUBECONFIG} get service nginx-service \
          -n ${NAMESPACE} -o jsonpath='{.status.loadBalancer.ingress[*].ip}'`
    
  6. curl를 사용하여 nginx 서버 IP 주소를 테스트합니다.

      curl http://$IP
    

삭제

이 튜토리얼에서 사용한 리소스 비용이 GDC 계정에 청구되지 않도록 하려면 만든 리소스를 삭제해야 합니다.

컨테이너 이미지 삭제

GDC 오프라인 환경에서 컨테이너 이미지를 삭제하려면 이미지가 포함된 Harbor 인스턴스를 삭제하거나 Harbor 인스턴스를 유지하고 개별 컨테이너 이미지를 삭제합니다.

관리형 Harbor 레지스트리에서 컨테이너 이미지를 삭제하려면 GDC 콘솔을 사용하세요.

  1. 탐색 메뉴의 CI/CD 섹션에서 Harbor Container Registry를 선택합니다.

  2. Harbor 인스턴스로 이동 외부 링크를 클릭합니다.

  3. Harbor UI를 사용하여 컨테이너 이미지를 삭제합니다. 자세한 내용은 Harbor 레지스트리 인스턴스 삭제를 참고하세요.

컨테이너 앱 삭제

배포된 컨테이너 앱을 삭제하려면 리소스가 포함된 GDC 프로젝트를 삭제하거나 GDC 프로젝트를 유지하고 개별 리소스를 삭제합니다.

개별 리소스를 삭제하려면 다음 단계를 완료합니다.

  1. 컨테이너 앱의 Service 객체를 삭제합니다.

    kubectl delete service nginx-service -n ${NAMESPACE}
    
  2. 컨테이너 앱의 Deployment 객체를 삭제합니다.

    kubectl delete deployment nginx-deployment -n ${NAMESPACE}
    
  3. 이 튜토리얼만을 위해 테스트 Kubernetes 클러스터를 만든 경우 삭제하세요.

    kubectl delete clusters.cluster.gdc.goog/USER_CLUSTER_NAME \
        -n platform --kubeconfig ${MANAGEMENT_API_SERVER}
    

    이렇게 하면 컴퓨팅 인스턴스, 디스크, 네트워크 리소스와 같이 Kubernetes 클러스터를 구성하는 리소스가 삭제됩니다.

다음 단계