3 - ECS Services

Updated 1 week ago by Michael Cretzman

This topic covers setting up a Harness Application and Service for an ECS Deployment, including the ECS container and service specifications for various scenarios.

Create the Harness ECS Application

The Harness Application represents a logical group of the ECS setup and release process, including the ECS service and task definitions, ECS cluster environment, and deployment workflow steps particular to each service you are deploying. For more information on Harness Applications, see Application Checklist.

To create a new Application, do the following:

  1. In Harness, click Setup, and then click Add Application. The Application dialog appears.
  2. Enter the name for your application, such as ECS Demo Application, and click SUBMIT. Your new Application appears.
  3. Click the Application name. The Application entities appear.

ECS and Infrastructure Provisioners

You can add a Harness Infrastructure Provisioner for CloudFormation or Terraform to your Harness Application and use the Infrastructure Provisioner to define the ECS infrastructure on the fly.

For more information, see Infrastructure Provisioners Overview.

Add a Harness ECS Service

A Harness Service represents your microservice as the artifact source (for example, Docker image), ECS container and service specifications, and any runtime variables used for deployment. You define where the artifact comes from, and you define the container and service specs for the ECS cluster. In addition, you can use configuration variables and files for the service.

Harness Services are different from ECS services. Where a Harness Service describes your microservice, an ECS service is a specified number of task definition instances run and maintained simultaneously in an Amazon ECS cluster. For a detailed description of ECS services, see Services from AWS.

In this guide, we will cover the how the following common ECS features are implemented in Harness Services:

  • Replica Strategy.
  • Daemon Strategy.
  • awsvpc Network Mode.
  • Service Discovery.

Configurations for these features are also discussed in the Harness Environment and Workflows, later in this guide. For the Harness Service artifact example, we will use a Docker image publicly hosted on Docker Hub.

To create a Harness Service for ECS, do the following:

  1. In Harness, click Setup. The list of Applications appears.
  2. Click the name of the ECS Application you created. The Application appears.
  3. Click Services. The Services page appears.
  4. Click Add Service. The Service dialog appears.
  5. In Name, enter a name for the service.
  6. In Deployment Type, select Amazon EC2 Container Services (ECS).
  7. Click SUBMIT. The new service is listed.
    Next, we will add the artifact source for the service, a sample app publicly hosted on Docker Hub.
  8. Click Add Artifact Source, and click Docker Registry.
  9. The Artifact Source dialog appears.
  10. In Source Server, select the Harness Artifact Server for the Docker Registry. For information on setting up a Harness Artifact Server, see Add Artifact Servers.
  11. In Docker Image Name, enter the name of the image.
  12. Click SUBMIT. The Artifact Source is added.

Next, we will define the ECS task definition and service specification.

ECS private registry authentication for tasks using AWS Secrets Manager enables you to store your credentials securely and then reference them in your container definition. For information on using private registry authentication for tasks, see Private Registry Authentication for Tasks from AWS.

Container Specification

You specify the ECS Task Definition in the Harness Service. To specify the ECS Task Definition, do the following:

  1. In the Harness Service, in Deployment Specification, expand ECS (if necessary). The Container Specification appears.
  2. Click Container Specification. The Container Specification dialog appears.
    You can specify the Task Definition using the fields in the dialog or click Advanced Settings to add or edit the JSON.

For a description of all available Task Definition parameters, see Task Definition Parameters from AWS.

The Container Definition JSON uses the following placeholders.

Placeholder

Description

${DOCKER_IMAGE_NAME}

Required. This placeholder is used with the image label in the JSON:

"image" : "${DOCKER_IMAGE_NAME}"

The placeholder is replaced with the Docker image name and tag at runtime.

${CONTAINER_NAME}

This placeholder is used with the name label in the JSON:

"name" : "${CONTAINER_NAME}"

The placeholder is replaced with a container name based on the Docker image name at runtime.

${EXECUTION_ROLE}

Required for Fargate. This placeholder is used with the executionRoleArn label in the JSON.

"executionRoleArn" : "${EXECUTION_ROLE}"

Replaced with executionRoleArn. When you register a task definition, you can provide a task execution role that allows the containers in the task to pull container images and publish container logs to CloudWatch on your behalf. For more information, see Amazon ECS Task Execution IAM Role from AWS.

If you have an existing Task Definition, you can paste it into the JSON. You can obtain the Task Definition from the ECS console:

You can also obtain the Task Definition using the AWS CLI (describe-task-definition):

aws ecs describe-task-definition --task-definition ecsTaskDefinitionName

Ensure that the required placeholders ${DOCKER_IMAGE_NAME} and ${EXECUTION_ROLE} (for Fargate) are used.

For some example Task Definitions, see Example Task Definitions from AWS.

Once Harness deploys the ECS application, you can see the placeholders replaced in the Task Definition JSON:

...
    "volumesFrom": [],

     "image": "registry.hub.docker.com/library/nginx:stable-perl",      ...

     "name": "library_nginx_stable-perl"

   }

For Fargate, you will see the executionRoleArn placeholder replaced:

{

 "ipcMode": null,

 "executionRoleArn": "arn:aws:iam::4XXX0225XX7:role/ecsTaskExecutionRole",

 "containerDefinitions": [

   {

...

awsvpc Network Mode

When configuring the Task Definition via the Harness Service Container Specification, you can set the awsvpc network mode by simply adding the networkMode parameter. For details Network Mode, see networkMode in the AWS docs.

Example for awsvpc Network Mode

The following example shows the networkMode parameter with the awsvpc value.

...

 "networkMode" : "awsvpc"

}

When you look at the Task Definition created by Harness, you can see the awsvpc network mode at the bottom of the definition JSON:

 ...

"pidMode": null,

 "requiresCompatibilities": [],

 "networkMode": "awsvpc",

 "cpu": null,

 "revision": 2,

 "status": "ACTIVE",

 "volumes": []

}

Task definitions that use the awsvpc network mode use the AWSServiceRoleForECS service-linked role, which is created for you automatically. For more information, see Using Service-Linked Roles for Amazon ECS from AWS.

Service Specification

You can specify the ECS service configuration in the Harness Service Service Specification. To specify the service configuration, do the following:

  1. In the Harness Service, in Deployment Specification, expand ECS (if necessary). The Service Specification appears.
By default, the Service Specification uses a Replica strategy.

If you have an existing service and you want to use its JSON in Service Specification, you can enter the JSON in Service Specification. You can enter in any parameter that is specified by the aws ecs create-service command.

You can obtain the JSON using the AWS CLI using describe-services:

aws ecs describe-services --cluster clusterName --service ecsServiceName

For information on all ECS Service definition parameters, see Service Definition Parameters from AWS.

The following sections describe how to configure the Service Specification for different ECS features.

Replica Strategy

You specify the Replica strategy using the schedulingStrategy parameter. By default, when you create a Harness Service using the Docker Image type, the Service Specification will generate the JSON for the Replica strategy. There are no changes that you need to make.

Example Service Specification for Replica Strategy

The following example is the default JSON generated for the Service Specification, setting the scheduling strategy for Replica:

{

"placementConstraints":[ ],

"placementStrategy":[ ],

"healthCheckGracePeriodSeconds":null,

"schedulingStrategy":"REPLICA"

}

Daemon Strategy

You specify the Daemon strategy using the schedulingStrategy parameter. By default, when you create a Harness Service using the Docker Image type, the Service Specification will generate the JSON for the Replica strategy. To set a Daemon strategy, you simply need to change the schedulingStrategy parameter to DAEMON.

Example Service Specification for Daemon Strategy

Here is an example of how to specify the Daemon scheduling strategy in Service Specification:

{

"placementConstraints":[ ],

"placementStrategy":[ ],

"healthCheckGracePeriodSeconds":null,

"schedulingStrategy":"DAEMON"

}

Service Discovery

Harness does not create an ECS Service Discovery Service, but Harness registers the ECS services it creates with the Service Discovery Service.

If you have configured Service Discovery for an ECS service, Harness can deploy to that service, registering its DNS SRV records as needed. During rollback or in the case of an ECS task failing, ECS manages the DNS resolution, replacing A records, etc.

For a detailed description of Service Discovery concepts, see Service Discovery from AWS. In you are new to Service Discovery, see Tutorial: Creating a Service Using Service Discovery from AWS.

Here is what the ECS Service Discovery configuration looks like in AWS:

When you create the Service Discovery Service in ECS, you will specify a namespace and ECS will generate the DNS records (SRV and A records) for the ECS namespace in AWS Route 53. DNS Queries for the namespace are resolved by Route 53 and traffic is routed to the instances supporting the ECS cluster.

To specify the Service Discovery Service in the Harness Service Specification, add the serviceRegistries parameter to the Harness Service Specification. The serviceRegistries parameter is defined like this:

"serviceRegistries": [

 {

   "registryArn": "arn:aws:servicediscovery:us-east-1:00000000:service/srv-jwyz7x4igkxckqno",

   "containerName": "${CONTAINER_NAME}",

   "containerPort": ${serviceVariable.containerPort}

   # "port":

 }

],

In this example, the Harness variable ${serviceVariable.containerPort} is used for the containerPort value. You can simply enter the port number instead, such as 8080. The ${serviceVariable.containerPort} variable is created in the Config Variables section of the Service as containerPort, and referenced as ${serviceVariable.containerPort} in the Service Specification. Using a Config Variable allows you to override the variable value when configuring the Harness Workflow that deploys the Service. For more information, see Workflow Phases.

The following list describes the fields and values needed for a Service Discovery Service in the Harness Service Specification:

  • registryArn - The Amazon Resource Name (ARN) of the service registry. The currently supported service registry is Amazon Route 53 Auto Naming. To obtain the registryArn value, use the aws ecs describe-services command.
  • containerName - The containerName field is the container name value to be used for your Service Discovery Service, and already specified in the task definition in Container Specification. Typically, you simply use the variable ${CONTAINER_NAME}. Harness verifies that the container name is specified in Container Specification.
  • containerPort - The port value to be used for your Service Discovery Service.

You can override Services variables in the Harness Environment and Workflow. For more information see Override a Service Configuration and Workflow Phases.

Which Service Parameters Do I Use?

Here are the guidelines for when to use the different service parameters in serviceRegistries:

  • If the task definition for your service task uses the awsvpc network mode and a SRV DNS record is used, you must specify either a containerName and containerPort combination or a port value, but not both.
  • If you use SRV DNS records, but not the awsvpc network mode, a containerName and containerPort combination is required.
  • If you use awsvpc network mode only (no SRV record), you do not need the containerName and containerPort, but can use port. The port field is used only if both the awsvpc network mode and SRV records are used.

Here is an example where the service task does not use the awsvpc network mode but a SRV DNS record is used:

"serviceRegistries": [

{

"registryArn": "arn:aws:servicediscovery:us-east-1:000000000000:service/srv-jwyz2x4igkxckqno",

"containerName": "${CONTAINER_NAME}",

"containerPort": ${serviceVariable.containerPort}

}

],

The value for containerName is ${CONTAINER_NAME}. This maps to the name field in the Container Specification, itself replaced with a container name based on the image name:

{

 "containerDefinitions" : [ {

   "name" : "${CONTAINER_NAME}",

   "image" : "${DOCKER_IMAGE_NAME}",

...

The value for containerPort is 8080.

    "portMappings" : [ {

     "containerPort" : 8080,

     "protocol" : "tcp"

   } ],
You can use Harness Environment variables to override the Service variables used in the Service Specification, thereby using the same Harness Service in multiple deployment environments. For more information, see Override a Service Configuration.

Using Private Docker Registry Authentication

In the Harness Service, you can add the RepositoryCredentials property type in the Container Specification to specify the repository credentials for private registry authentication.

This process has the following steps:

  1. Add the secretsmanager:GetSecretValue policy to the ECS task execution role. Here is the policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"secretsmanager:GetSecretValue"
],
"Resource": [
"arn:aws:secretsmanager:region:aws_account_id:secret:secret_name",
"arn:aws:kms:region:aws_account_id:key:key_id"
]
}
]
}
The action kms:Decrypt is required only if your key uses a custom KMS key and not the default key. The ARN for your custom key should be added as a resource. For more information, and details about ECS platform versions that support this feature, see Private Registry Authentication for Tasks from AWS.
  1. Add the RepositoryCredentials property type to the Harness Service as a part of the Task Definition in Container Specification like this:
"containerDefinitions": [

{

"name" : "${CONTAINER_NAME}",

  "image" : "${DOCKER_IMAGE_NAME}",...

  "repositoryCredentials": {

    "credentialsParameter": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name"

  }

...

}

]
  1. In addition to specifying the repositoryCredentials, you must also specify the Task execution role in the Service Container Specification for the Task Definition using the property executionRoleArn. This role authorizes Amazon ECS to pull private images for your task. For more information, see Private Registry Authentication Required IAM Permissions. For example:

"executionRoleArn" : "arn:aws:iam::448000000317:role/ecsTaskExecutionRole",

The Task execution role is specified when the Task Definition is created in ECS, or in AWS IAM (see Amazon ECS Task Execution Role). If you are creating the ECS Task Definition for the first time using Harness, create the role in IAM, and then add it in executionRoleArn in Container Specification.

Next

Now that you have set up your Harness Artifact Server and Cloud Provider and ECS Service, you can create the Harness Environment to identify your target ECS cluster:


How did we do?