커스텀 서비스 계정을 사용하여 작업 액세스 제어

이 문서에서는 작업의 VM이 액세스할 수 있는 리소스 및 애플리케이션에 영향을 주는 Batch 작업의 서비스 계정을 지정하는 방법을 설명합니다. 커스텀 서비스 계정을 지정하지 않으면 작업이 기본적으로 프로젝트의 모든 VM에 자동으로 연결되는 Compute Engine 기본 서비스 계정을 사용하도록 지정됩니다. 따라서 커스텀 서비스 계정을 사용하면 작업 권한을 보다 확실하게 관리할 수 있으며 권한을 제한하는 데 효과적입니다.

작업의 서비스 계정에 대해 자세히 알아보세요.

시작하기 전에

  1. Batch를 사용한 적이 없으면 Batch 시작하기를 검토하고 프로젝트 및 사용자 기본 요건을 완료하여 Batch를 사용 설정하세요.
  2. 맞춤 서비스 계정을 사용하여 작업의 액세스를 제어하는 데 필요한 권한을 얻으려면 관리자에게 다음 IAM 역할을 부여해 달라고 요청하세요.

    역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.

    커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.

  3. 이 작업에 사용할 서비스 계정을 찾습니다. 이 서비스 계정에 작업을 실행하는 데 필요한 모든 권한이 있는지 확인하세요.

    서비스 계정 보기작업의 서비스 계정에 필요한 권한에 대해 자세히 알아보세요.

커스텀 서비스 계정을 사용하는 작업 만들기

커스텀 서비스 계정을 사용하는 작업을 만들려면 다음 방법 중 하나를 선택합니다.

  • 이 섹션에 표시된 것처럼 작업 정의에 커스텀 서비스 계정을 지정합니다.
  • Compute Engine 인스턴스 템플릿을 사용하고 인스턴스 템플릿과 작업 정의 모두에 커스텀 서비스 계정을 지정합니다.

이 섹션에서는 커스텀 서비스 계정을 사용하는 작업을 만드는 방법에 대한 예시를 제공합니다. gcloud CLI, Batch API, Java, Node.js 또는 Python을 사용하여 커스텀 서비스 계정을 사용하는 작업을 만들 수 있습니다.

gcloud

gcloud CLI를 사용하여 커스텀 서비스 계정을 사용하는 작업을 만들려면 gcloud batch jobs submit 명령어를 사용하여 작업의 구성 파일에 커스텀 서비스 계정을 지정합니다.

예를 들어 커스텀 서비스 계정을 사용하는 스크립트 작업을 만들려면 다음 안내를 따르세요.

  1. 현재 디렉터리에 다음 콘텐츠로 hello-world-service-account.json이라는 JSON 파일을 만듭니다.

    {
        "taskGroups": [
            {
                "taskSpec": {
                    "runnables": [
                        {
                            "script": {
                                "text": "echo Hello World! This is task $BATCH_TASK_INDEX."
                            }
                        }
                    ]
                }
            }
        ],
        "allocationPolicy": {
            "serviceAccount": {
                "email": "SERVICE_ACCOUNT_EMAIL"
            }
        }
    }
    

    여기서 SERVICE_ACCOUNT_EMAIL은 서비스 계정의 이메일 주소입니다. serviceAccount 필드를 지정하지 않았으면 값이 기본 Compute Engine 서비스 계정으로 설정됩니다.

  2. 다음 명령어를 실행합니다.

    gcloud batch jobs submit example-service-account-job \
      --location us-central1 \
      --config hello-world-service-account.json
    

API

Batch API를 사용하여 커스텀 서비스 계정을 사용하는 작업을 만들려면 jobs.create 메서드를 사용하고 allocationPolicy 필드에 커스텀 서비스 계정을 지정합니다.

예를 들어 커스텀 서비스 계정을 사용하는 스크립트 작업을 만들려면 다음 요청을 수행합니다.

POST https://batch.googleapis.com/v1/projects/PROJECT_ID/locations/us-central1/jobs?job_id=example-service-account-job

{
    "taskGroups": [
        {
            "taskSpec": {
                "runnables": [
                    {
                        "script": {
                            "text": "echo Hello World! This is task $BATCH_TASK_INDEX."
                        }
                    }
                ]
            }
        }
    ],
    "allocationPolicy": {
        "serviceAccount": {
            "email": "SERVICE_ACCOUNT_EMAIL"
        }
    }
}

다음을 바꿉니다.

자바


import com.google.cloud.batch.v1.AllocationPolicy;
import com.google.cloud.batch.v1.BatchServiceClient;
import com.google.cloud.batch.v1.CreateJobRequest;
import com.google.cloud.batch.v1.Job;
import com.google.cloud.batch.v1.LogsPolicy;
import com.google.cloud.batch.v1.LogsPolicy.Destination;
import com.google.cloud.batch.v1.Runnable;
import com.google.cloud.batch.v1.Runnable.Script;
import com.google.cloud.batch.v1.ServiceAccount;
import com.google.cloud.batch.v1.TaskGroup;
import com.google.cloud.batch.v1.TaskSpec;
import com.google.protobuf.Duration;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CreateBatchUsingServiceAccount {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "YOUR_PROJECT_ID";
    // Name of the region you want to use to run the job. Regions that are
    // available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
    String region = "europe-central2";
    // The name of the job that will be created.
    // It needs to be unique for each project and region pair.
    String jobName = "JOB_NAME";
    // The email address of your service account.
    String serviceAccountEmail = "EMAIL";

    createBatchUsingServiceAccount(projectId, region, jobName, serviceAccountEmail);
  }

  // Create a job that uses a custom service account
  public static Job createBatchUsingServiceAccount(String projectId, String region, String jobName,
                                                   String serviceAccountEmail)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (BatchServiceClient batchServiceClient = BatchServiceClient.create()) {
      // Define what will be done as part of the job.
      Runnable runnable =
          Runnable.newBuilder()
              .setScript(
                  Script.newBuilder()
                      .setText(
                          "echo Hello world! This is task ${BATCH_TASK_INDEX}. "
                                  + "This job has a total of ${BATCH_TASK_COUNT} tasks.")
                      // You can also run a script from a file. Just remember, that needs to be a
                      // script that's already on the VM that will be running the job.
                      // Using setText() and setPath() is mutually exclusive.
                      // .setPath("/tmp/test.sh")
                      .build())
              .build();

      TaskSpec task = TaskSpec.newBuilder()
              // Jobs can be divided into tasks. In this case, we have only one task.
              .addRunnables(runnable)
              .setMaxRetryCount(2)
              .setMaxRunDuration(Duration.newBuilder().setSeconds(3600).build())
              .build();

      // Tasks are grouped inside a job using TaskGroups.
      // Currently, it's possible to have only one task group.
      TaskGroup taskGroup = TaskGroup.newBuilder()
          .setTaskCount(3)
          .setParallelism(1)
          .setTaskSpec(task)
          .build();

      ServiceAccount.Builder serviceAccount = ServiceAccount.newBuilder();

      // If the serviceAccount field is not specified,
      // the value is set to the default Compute Engine service account.
      if (serviceAccountEmail != null) {
        serviceAccount.setEmail(serviceAccountEmail);
      }

      // Attach service account that VMs will run as.
      AllocationPolicy allocationPolicy = AllocationPolicy.newBuilder()
              .setServiceAccount(serviceAccount)
              .build();

      Job job =
          Job.newBuilder()
              .addTaskGroups(taskGroup)
              .setAllocationPolicy(allocationPolicy)
              .putLabels("env", "testing")
              .putLabels("type", "script")
              // We use Cloud Logging as it's an out of the box available option.
              .setLogsPolicy(
                  LogsPolicy.newBuilder().setDestination(Destination.CLOUD_LOGGING))
              .build();

      CreateJobRequest createJobRequest =
          CreateJobRequest.newBuilder()
              // The job's parent is the region in which the job will run.
              .setParent(String.format("projects/%s/locations/%s", projectId, region))
              .setJob(job)
              .setJobId(jobName)
              .build();

      Job result =
          batchServiceClient
              .createJobCallable()
              .futureCall(createJobRequest)
              .get(5, TimeUnit.MINUTES);

      System.out.printf("Successfully created the job: %s", result.getName());

      return result;
    }
  }
}

Node.js

// Imports the Batch library
const batchLib = require('@google-cloud/batch');
const batch = batchLib.protos.google.cloud.batch.v1;
// Instantiates a client
const batchClient = new batchLib.v1.BatchServiceClient();

async function main() {
  /**
   * TODO(developer): Update these variables before running the sample.
   */
  // Project ID or project number of the Google Cloud project you want to use.
  const projectId = await batchClient.getProjectId();
  // Name of the region you want to use to run the job. Regions that are
  // available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
  const region = 'europe-central2';
  // The name of the job that will be created.
  // It needs to be unique for each project and region pair.
  const jobName = 'batch-service-account-job';
  /**
   * TODO(developer): Uncomment and update serviceAccountEmail if you do not want to use default Compute Engine service account.
   */
  // The email address of your service account.
  // const serviceAccountEmail = 'email';
  let serviceAccountEmail;

  // Define what will be done as part of the job.
  const runnable = new batch.Runnable({
    script: new batch.Runnable.Script({
      commands: ['-c', 'echo Hello world! This is task ${BATCH_TASK_INDEX}.'],
    }),
  });

  const task = new batch.TaskSpec({
    runnables: [runnable],
    maxRetryCount: 2,
    maxRunDuration: {seconds: 3600},
  });

  // Tasks are grouped inside a job using TaskGroups.
  const group = new batch.TaskGroup({
    taskCount: 3,
    taskSpec: task,
  });

  const serviceAccount = new batch.ServiceAccount();

  if (serviceAccountEmail) {
    serviceAccount.email = serviceAccountEmail;
  }

  const allocationPolicy = new batch.AllocationPolicy({
    // If the serviceAccount field is not specified, the value is set to the default Compute Engine service account.
    serviceAccount,
  });

  const job = new batch.Job({
    name: jobName,
    taskGroups: [group],
    labels: {env: 'testing', type: 'script'},
    allocationPolicy,
    // We use Cloud Logging as it's an option available out of the box
    logsPolicy: new batch.LogsPolicy({
      destination: batch.LogsPolicy.Destination.CLOUD_LOGGING,
    }),
  });

  // The job's parent is the project and region in which the job will run
  const parent = `projects/${projectId}/locations/${region}`;

  async function callCreateBatchServiceAccountJob() {
    // Construct request
    const request = {
      parent,
      jobId: jobName,
      job,
    };

    // Run request
    const [response] = await batchClient.createJob(request);
    console.log(JSON.stringify(response));
  }
  await callCreateBatchServiceAccountJob();

Python

from google.cloud import batch_v1


def create_with_custom_service_account_job(
    project_id: str, region: str, job_name: str, service_account_email: str
) -> batch_v1.Job:
    """
    This method shows how to create a sample Batch Job that will run
    a simple command on Cloud Compute instances with custom service account.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        region: name of the region you want to use to run the job. Regions that are
            available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
        job_name: the name of the job that will be created.
            It needs to be unique for each project and region pair.
        service_account_email: custom service account email

    Returns:
        A job object representing the job created.
    """
    client = batch_v1.BatchServiceClient()

    # Define what will be done as part of the job.
    task = batch_v1.TaskSpec()
    runnable = batch_v1.Runnable()
    runnable.script = batch_v1.Runnable.Script()
    runnable.script.text = "echo Hello world! from task ${BATCH_TASK_INDEX}. This job has a total of ${BATCH_TASK_COUNT} tasks."
    task.runnables = [runnable]
    task.max_retry_count = 2
    task.max_run_duration = "3600s"

    # Tasks are grouped inside a job using TaskGroups.
    # Currently, it's possible to have only one task group.
    group = batch_v1.TaskGroup()
    group.task_count = 4
    group.task_spec = task

    # Policies are used to define on what kind of virtual machines the tasks will run on.
    # Read more about local disks here: https://cloud.google.com/compute/docs/disks/persistent-disks
    policy = batch_v1.AllocationPolicy.InstancePolicy()
    policy.machine_type = "e2-standard-4"
    instances = batch_v1.AllocationPolicy.InstancePolicyOrTemplate()
    instances.policy = policy
    allocation_policy = batch_v1.AllocationPolicy()
    allocation_policy.instances = [instances]

    # Defines the service account for Batch-created VMs. If omitted, the [default account]
    # More details: https://cloud.google.com/compute/docs/access/service-accounts#default_service_account
    service_account = batch_v1.ServiceAccount()
    service_account.email = service_account_email
    allocation_policy.service_account = service_account

    job = batch_v1.Job()
    job.task_groups = [group]
    job.allocation_policy = allocation_policy
    job.labels = {"env": "testing", "type": "script"}

    create_request = batch_v1.CreateJobRequest()
    create_request.job = job
    create_request.job_id = job_name
    # The job's parent is the region in which the job will run
    create_request.parent = f"projects/{project_id}/locations/{region}"

    return client.create_job(create_request)

다음 단계