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


이 튜토리얼에서는 Google Distributed Cloud (GDC) 오프라인 어플라이언스 환경에서 컨테이너 애플리케이션을 업로드하고 어플라이언스 환경에서 해당 애플리케이션을 실행하는 방법을 설명합니다. 이 튜토리얼에서는 Harbor 프로젝트를 만들고, 이미지를 Harbor에 업로드하고, 워크로드를 만드는 방법을 알아봅니다. 컨테이너화된 워크로드는 프로젝트 네임스페이스 내에서 실행됩니다.

GDC 에어 갭 어플라이언스 환경에는 tear이라는 GDC 프로젝트에 tear-harbor라는 Harbor 레지스트리가 사전 구성되어 있습니다. 이 예에서는 이 레지스트리를 사용합니다.

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

목표

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

시작하기 전에

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

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

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

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

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

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

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

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

    export KUBECONFIG=CLUSTER_KUBECONFIG
    

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

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

Harbor as a Service를 사용하려면 tear-harbor 레지스트리 인스턴스 내에 Harbor 프로젝트를 만들어 컨테이너 이미지를 관리해야 합니다.

  1. tear-harbor의 URL이 필요합니다. 인스턴스의 URL을 나열합니다.

    gdcloud harbor instances describe tear-harbor --project=tear
    

    출력은 harbor-1.org-1.zone1.google.gdc.test과 비슷합니다.

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

    export INSTANCE_URL=INSTANCE_URL
    
  3. 프로젝트를 만들기 전에 이전 단계의 URL을 사용하여 Harbor에 로그인해야 합니다. 브라우저를 사용하여 이 URL을 열고 Harbor 인스턴스에 로그인합니다.

  4. Harbor 프로젝트를 만듭니다.

    gdcloud harbor harbor-projects create HARBOR_PROJECT \
        --project=tear \
        --instance=tear-harbor
    

    HARBOR_PROJECT을 만들 Harbor 프로젝트의 이름으로 바꿉니다. 프로젝트 네임스페이스에서는 Harbor 프로젝트를 만들 수 없습니다. tear 프로젝트를 사용해야 합니다.

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

    export HARBOR_PROJECT=HARBOR_PROJECT
    

Docker 구성

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

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

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

  3. tear-harbor는 사전 구성된 Harbor 레지스트리이므로 Google Distributed Cloud 오프라인 내부 CA에서 서명한 인증서를 신뢰해야 합니다.

    1. IO에게 다음 정보를 요청하세요.

      1. Harbor 클러스터의 외부 URL입니다.
      2. Google Distributed Cloud 에어 갭 적용 내부 CA의 .crt 파일입니다. 파일은 일반적으로 anthos-creds 네임스페이스의 trust-store-internal-only 이름으로 컨트롤 플레인에 보안 비밀로 저장됩니다.
    2. 이전 단계와 마찬가지로 Harbor 클러스터의 외부 URL 이름으로 폴더를 만들고 폴더 내에 .crt 파일을 보관합니다.

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

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

  1. Harbor 프로젝트 로봇 계정을 추가합니다. Harbor UI의 단계에 따라 로봇 계정을 만들고 로봇 비밀 토큰을 복사합니다(https://goharbor.io/docs/2.8.0/working-with-projects/project-configuration/create-robot-accounts/#add-a-robot-account).

  2. 다음과 같은 문법을 갖는 새 로봇 프로젝트 계정 이름을 확인합니다.

    <PREFIX><PROJECT_NAME>+<ACCOUNT_NAME>
    

    예를 들어 로봇 프로젝트 계정 이름 형식은 harbor@library+artifact-account와 유사합니다.

    Harbor에서 로봇 프로젝트 계정 이름을 찾는 방법에 관한 자세한 내용은 Harbor 문서를 참고하세요(https://goharbor.io/docs/2.8.0/working-with-projects/project-configuration/create-robot-accounts/#view-project-robot-accounts).

  3. Harbor 프로젝트 로봇 계정 및 비밀 토큰으로 Docker에 로그인합니다.

    docker login ${INSTANCE_URL}
    

    메시지가 표시되면 Username에 로봇 프로젝트 계정 이름을 삽입하고 Password에 보안 토큰을 삽입합니다.

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

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

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

    다음을 바꿉니다.

    • DOCKER_CONFIG: .docker/config.json 파일의 경로입니다.
    • NAMESPACE: 생성하는 보안 비밀의 네임스페이스입니다.

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

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

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

    docker pull gcr.io/cloud-marketplace/google/nginx:1.25
    
  2. 이미지 이름을 설정합니다. 전체 이미지 이름의 형식은 다음과 같습니다.

    ${INSTANCE_URL}/${HARBOR_PROJECT}/nginx
    
  3. 저장소 이름으로 로컬 이미지에 태그를 지정합니다.

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

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

샘플 컨테이너 앱 배포

이제 nginx 컨테이너 이미지를 어플라이언스 클러스터에 배포할 수 있습니다.

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

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

nginx 웹 서버를 배포합니다.

  1. 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
    
  2. 포드가 배포에 의해 생성되었는지 확인합니다.

    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
    
  3. 네임스페이스로의 모든 네트워크 트래픽을 허용하는 네트워크 정책을 만듭니다.

    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
    
  4. nginx 서비스의 IP 주소를 내보냅니다.

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

      curl http://$IP
    

다음 단계

  • 컨테이너 관리 방법에 대한 자세한 내용은 컨테이너 문서를 참고하세요.