Kubernetes manifest를 Nomad job specification으로 변환

Kubernetes manifest를 Nomad job specification으로 변환

Kubernetes와 Nomad의 워크로드는 둘 다 선언적 스펙 파일로 정의돼요. Kubernetes 워크로드 스펙 파일은 manifest 로 알려져 있고 YAML로 작성해요. Nomad 워크로드 스펙 파일은 job specification 또는 jobspec 으로 알려져 있고 HCL로 만들어요.

이 페이지는 Kubernetes manifest로 정의된 예시 애플리케이션을 사용해 동등한 Nomad jobspec을 만드는 과정을 안내해요.

출처: 문서

본문

예시 Kubernetes 애플리케이션 검토 (Review an example Kubernetes application)

다음 예시 애플리케이션은 AWS EKS 문서의 Linux에 샘플 애플리케이션 배포 가이드에서 가져온 거예요.

이 애플리케이션은 각각 포트 8080에서 리슨하는 NGINX 컨테이너 세 개와, 포트 80에서 리슨하며 요청을 NGINX 컨테이너로 전달하는 서비스 하나를 포함해요. 컨테이너는 amd64 또는 arm64 아키텍처의 Linux 노드에서 실행돼요. 이 애플리케이션은 Deployment manifest와 Service manifest로 구성돼요.

sample-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: eks-sample-linux-deployment
  namespace: eks-sample-app
  labels:
    app: eks-sample-linux-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: eks-sample-linux-app
  template:
    metadata:
      labels:
        app: eks-sample-linux-app
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/arch
                operator: In
                values:
                - amd64
                - arm64
      containers:
      - name: nginx
        image: public.ecr.aws/nginx/nginx:1.23
        ports:
        - name: http
          containerPort: 8080
        imagePullPolicy: IfNotPresent
      nodeSelector:
        kubernetes.io/os: linux

apiVersion: v1
kind: Service
metadata:
  name: eks-sample-linux-service
  namespace: eks-sample-app
  labels:
    app: eks-sample-linux-app
spec:
  selector:
    app: eks-sample-linux-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Nomad jobspec 시작 방법 (How to start a Nomad jobspec)

변환 프로세스를 시작하려면 job, group, task 블록을 포함하는 jobspec 파일의 프레임워크를 만들어요.

sample-app.nomad.acl

job "eks-sample-linux-deployment" {
    
  group "nginx-group" {

    task "nginx" {
      
    }
  }
}

이 예시들의 명명 체계는 동등한 구성 속성을 강조하기 위해 원래 Kubernetes manifest와 같은 eks- 접두사를 사용해요. 이 경우 Nomad job 리소스의 이름은 Kubernetes Deployment name과 같아요.

NGINX 컨테이너 집합을 배포하려면 group 블록을 구성해요. count 속성은 Nomad에 동일한 컨테이너 세 개를 만들도록 지시하고, network 블록은 포트 8080을 활성화하고 http라는 이름으로 태스크 구성에 동적으로 사용할 수 있게 해요. 각 컨테이너는 config 블록에 정의된 이미지와 구성을 사용하고, driver 속성은 Nomad에 Docker 런타임을 사용하도록 지시해요. 태스크 구성은 또한 그룹 레벨에 정의된 http 포트를 사용해요.

sample-app.nomad.acl

job "eks-sample-linux-deployment" {
    
  group "nginx-group" {
    count = 3

    network {
      port "http" { 
        to = 8080
      }
    }

    task "nginx" {
      driver = "docker"

      config {
        image = "public.ecr.aws/nginx/nginx:1.23"
        ports = ["http"]
      }
    }
  }
}

워크로드가 실행되는 곳 제한 (Limit where the workloads run)

Nomad는 워크로드 요구 사항에 따라 constraints와 affinities를 태스크, 그룹 또는 잡 레벨에서 설정할 수 있게 해요.

예시 Kubernetes 애플리케이션은 amd64 또는 arm64 아키텍처의 노드에서 실행되도록 스케줄링 중에 실행되는 affinity를 구성해요. linux 런타임은 컨테이너의 nodeSelector 구성에 설정돼요.

Nomad에서는 affinity 블록을 job 정의에 추가해요. 각 affinity는 각 아키텍처가 선택될 동등한 기회를 가지도록 가중치 50으로 설정돼요. 그런 다음 task 블록에 constraint를 설정해요.

sample-app.nomad.acl

job "eks-sample-linux-deployment" {
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "amd64"
    weight = 50
  }
 
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "arm64"
    weight = 50
  }
    
  group "nginx-group" {
    count = 3

    network {
      port "http" { 
        to = 8080
      }
    }

    task "nginx" {
      driver = "docker"

      constraint {
        attribute = "${attr.kernel.name}"
        value = "linux"
      }

      config {
        image = "public.ecr.aws/nginx/nginx:1.23"
        ports = ["http"]
      }
    }
  }
}

잡 타입 설정 (Set job type)

Nomad는 service, system, batch, system batch 잡 타입을 지원해요. 이 예시 애플리케이션은 service예요. 잡 타입에 대한 자세한 내용은 문서의 Nomad job schedulers를 참고하세요.

잡 타입을 설정한 다음 네임스페이스와 사용자 정의 레이블을 포함한 잡 메타데이터를 job 블록에 추가해요. 네임스페이스를 사용하려면 잡을 실행하기 전에 네임스페이스 객체를 구성해야 해요.

sample-app.nomad.acl

job "eks-sample-linux-deployment" {
  type = "service"
  namespace = "eks-sample-app"
  datacenters = ["*"]
  meta {
    app = "eks-sample-linux-app"
  }
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "amd64"
    weight = 50
  }
 
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "arm64"
    weight = 50
  }
    
  group "nginx-group" {
    count = 3

    network {
      port "http" { 
        to = 8080
      }
    }

    task "nginx" {
      driver = "docker"

      constraint {
        attribute = "${attr.kernel.name}"
        value = "linux"
      }

      config {
        image = "public.ecr.aws/nginx/nginx:1.23"
        ports = ["http"]
      }
    }
  }
}

마지막으로 Nomad가 세 컨테이너를 모두 노출하도록 service 블록을 group 구성에 추가해요.

Nomad에는 내장 서비스 디스커버리가 있어 그룹 레벨에 service 블록을 추가하면 서비스 이름이 그룹의 task 블록에 정의된 세 할당 중 어느 것으로든 트래픽을 보낼 수 있어요. 그룹 레벨에 service 블록을 추가하면 Consul service mesh 통합을 사용할 수도 있게 돼요.

sample-app.nomad.acl

job "eks-sample-linux-deployment" {
  type = "service"
  namespace = "eks-sample-app"
  datacenters = ["*"]
  meta {
    app = "eks-sample-linux-app"
  }
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "amd64"
    weight = 50
  }
 
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "arm64"
    weight = 50
  }
    
  group "nginx-group" {
    count = 3

    network {
      port "http" { 
        to = 8080
      }
    }

    service {
      name = "eks-sample-linux-service"
      provider = "nomad"
      port = "80"
    }

    task "nginx" {
      driver = "docker"

      constraint {
        attribute = "${attr.kernel.name}"
        value = "linux"
      }

      config {
        image = "public.ecr.aws/nginx/nginx:1.23"
        ports = ["http"]
      }
    }
  }
}

이제 Nomad jobspec이 완성되었고, CLI 또는 Web UI로 Nomad에서 잡을 실행할 수 있어요. 테스트 환경이 필요하면 HashiCorp의 Nomad sandbox를 사용해 호스팅 세션을 시작하세요.

예시 코드 비교 (Example code comparisons)

이 구성 스니펫들은 manifest 또는 jobspec의 일부를 나타내요. 추가 명확성을 위해 탭에 나란히 표시돼 있어요.

네임스페이스 (Namespace)

Kubernetes Nomad
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: eks-sample-app
job "eks-sample-linux-deployment" {
  namespace = "eks-sample-app"
}

메타데이터 (Metadata)

메타데이터는 배포 또는 잡의 이름과 사용자 정의 메타데이터를 포함해요.

Kubernetes Nomad
apiVersion: apps/v1
kind: Deployment
metadata:
  name: eks-sample-linux-deployment
  namespace: eks-sample-app
  labels:
    app: eks-sample-linux-app
job "eks-sample-linux-deployment" {
  meta {
    app = "eks-sample-linux-app"
  }
}

컨테이너 스펙과 count (Container specification and count)

Kubernetes Nomad
apiVersion: apps/v1
kind: Deployment

spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: nginx
        image: public.ecr.aws/nginx/nginx:1.23
        ports:
        - name: http
          containerPort: 8080
job "eks-sample-linux-deployment" {
    
  group "nginx-group" {
    count = 3

    task "nginx" {
      driver = "docker"

      config {
        image = "public.ecr.aws/nginx/nginx:1.23"
        ports = "80"
      }
    }
  }
}

Affinity

Kubernetes Nomad
apiVersion: apps/v1
kind: Deployment

spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/arch
                operator: In
                values:
                - amd64
                - arm64
job "eks-sample-linux-deployment" {
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "amd64"
    weight = 50
  }
 
  affinity {
    attribute = "${attr.cpu.arch}"
    value = "arm64"
    weight = 50
  }
}

노드 선택기와 제약 조건 (Node selector and constraint)

Kubernetes Nomad
apiVersion: apps/v1
kind: Deployment

spec:
  template:
    spec:
      nodeSelector:
        kubernetes.io/os: linux
job "eks-sample-linux-deployment" {
    
  group "nginx-group" {

    task "nginx" {

      constraint {
        attribute = "${attr.kernel.name}"
        value = "linux"
      }
    }
  }
}

서비스 (Service)

Kubernetes는 kind가 Service로 설정된 별도의 구성 manifest로 서비스를 정의한다는 점에 유의하세요. Nomad jobspec은 서비스와 태스크 정의를 모두 포함해요.

Kubernetes Nomad
apiVersion: v1
kind: Service
metadata:
  name: eks-sample-linux-service
  namespace: eks-sample-app
  labels:
    app: eks-sample-linux-app
spec:
  selector:
    app: eks-sample-linux-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
job "eks-sample-linux-deployment" {
    
  group "nginx-group" {

    service {
      name = "eks-sample-linux-service"
      provider = "nomad"
      port = "80"
    }
  }
}

다음 단계 (Next steps)

Nomad 잡과 통합에 대해 계속 배우려면 다음 리소스를 확인하세요:

더 알아보기 (Learn more)