Kubernetes 호스팅

Kubernetes는 Orleans 애플리케이션을 호스팅하는 데 널리 사용되는 제품입니다. Orleans는 특정 구성 없이 Kubernetes에서 실행되지만 호스팅 플랫폼이 제공할 수 있는 추가 지식을 활용할 수도 있습니다.

Microsoft.Orleans.Hosting.Kubernetes 패키지는 Kubernetes 클러스터에서 Orleans 애플리케이션을 호스팅하기 위한 통합을 추가합니다. 이 패키지는 다음 작업을 수행하는 확장 메서드인 UseKubernetesHosting을 제공합니다.

  • SiloOptions.SiloName은 Pod 이름으로 설정됩니다.
  • EndpointOptions.AdvertisedIPAddress는 Pod IP로 설정됩니다.
  • EndpointOptions.SiloListeningEndpointEndpointOptions.GatewayListeningEndpoint는 구성된 SiloPortGatewayPort와 함께 모든 주소를 수신 대기하도록 구성됩니다. 값이 명시적으로 설정되지 않은 경우 1111130000의 기본 포트 값이 사용됩니다.
  • ClusterOptions.ServiceId는 이름이 orleans/serviceId인 Pod 레이블의 값으로 설정됩니다.
  • ClusterOptions.ClusterId는 이름이 orleans/clusterId인 Pod 레이블의 값으로 설정됩니다.
  • 시작 프로세스 초기에 사일로는 Kubernetes를 프로브하여 해당 Pod가 없는 사일로를 찾고 해당 사일로를 중지된 것으로 표시합니다.
  • Kubernetes의 API 서버에서 부하를 제거하기 위해 모든 사일로의 하위 집합에 대해 동일한 프로세스가 런타임에 발생합니다. 기본적으로 클러스터의 사일로 2개는 Kubernetes를 감시합니다.

Kubernetes 호스팅 패키지는 클러스터링에 Kubernetes를 사용하지 않습니다. 클러스터링의 경우 별도의 클러스터링 공급자가 여전히 필요합니다. 클러스터링 구성에 대한 자세한 내용은 서버 구성 설명서를 참조하세요.

이 기능을 사용하려면 서비스를 배포하는 방법에 대한 몇 가지 요구 사항을 따라야 합니다.

  • 사일로 이름은 Pod 이름과 일치해야 합니다.
  • Pod에는 사일로 ServiceIdClusterId에 해당하는 orleans/serviceIdorleans/clusterId 레이블이 있어야 합니다. 위에서 언급한 메서드는 환경 변수에서 해당 레이블을 Orleans의 해당 옵션으로 전파합니다.
  • Pod에는 환경 변수(POD_NAME, POD_NAMESPACE, POD_IP, ORLEANS_SERVICE_ID, ORLEANS_CLUSTER_ID)가 설정되어 있어야 합니다.

다음 예제에서는 이러한 레이블 및 환경 변수를 올바르게 구성하는 방법을 보여 줍니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dictionary-app
  labels:
    orleans/serviceId: dictionary-app
spec:
  selector:
    matchLabels:
      orleans/serviceId: dictionary-app
  replicas: 3
  template:
    metadata:
      labels:
        # This label is used to identify the service to Orleans
        orleans/serviceId: dictionary-app

        # This label is used to identify an instance of a cluster to Orleans.
        # Typically, this will be the same value as the previous label, or any
        # fixed value.
        # In cases where you are not using rolling deployments (for example,
        # blue/green deployments),
        # this value can allow for distinct clusters which do not communicate
        # directly with each others,
        # but which still share the same storage and other resources.
        orleans/clusterId: dictionary-app
    spec:
      containers:
        - name: main
          image: my-registry.azurecr.io/my-image
          imagePullPolicy: Always
          ports:
          # Define the ports which Orleans uses
          - containerPort: 11111
          - containerPort: 30000
          env:
          # The Azure Storage connection string for clustering is injected as an
          # environment variable
          # It must be created separately using a command such as:
          # > kubectl create secret generic az-storage-acct `
          #     --from-file=key=./az-storage-acct.txt
          - name: STORAGE_CONNECTION_STRING
            valueFrom:
              secretKeyRef:
                name: az-storage-acct
                key: key
          # Configure settings to let Orleans know which cluster it belongs to
          # and which pod it is running in
          - name: ORLEANS_SERVICE_ID
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['orleans/serviceId']
          - name: ORLEANS_CLUSTER_ID
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['orleans/clusterId']
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
          - name: DOTNET_SHUTDOWNTIMEOUTSECONDS
            value: "120"
          request:
            # Set resource requests
      terminationGracePeriodSeconds: 180
      imagePullSecrets:
        - name: my-image-pull-secret
  minReadySeconds: 60
  strategy:
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1

RBAC 사용 클러스터의 경우 Pod에 대한 Kubernetes 서비스 계정에 필요한 액세스 권한을 부여해야 할 수도 있습니다.

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: orleans-hosting
rules:
- apiGroups: [ "" ]
  resources: ["pods"]
  verbs: ["get", "watch", "list", "delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: orleans-hosting-binding
subjects:
- kind: ServiceAccount
  name: default
  apiGroup: ''
roleRef:
  kind: Role
  name: orleans-hosting
  apiGroup: ''

활동성, 준비 상태 및 시작 프로브

Kubernetes는 Pod를 프로브하여 서비스의 상태를 확인할 수 있습니다. 자세한 내용은 Kubernetes 설명서에서 활동성, 준비 상태 및 시작 프로브 구성을 참조하세요.

Orleans는 클러스터 멤버 자격 프로토콜을 사용하여 프로세스 또는 네트워크 오류를 즉시 감지하고 복구합니다. 각 노드는 다른 노드의 하위 집합을 모니터링하여 주기적인 프로브를 보냅니다. 노드가 다른 여러 노드의 여러 연속 프로브에 응답하지 못하면 클러스터에서 강제로 제거됩니다. 실패한 노드가 제거되었음을 알게 되면 즉시 종료됩니다. Kubernetes는 종료된 프로세스를 다시 시작하고 클러스터에 다시 참가하려고 시도합니다.

Kubernetes의 프로브는 Pod의 프로세스가 실행 중이며 좀비 상태에 갇혀 있지 않은지 여부를 확인하는 데 도움이 될 수 있습니다. 프로브는 Pod 간 연결 또는 응답성을 확인하거나 애플리케이션 수준 기능 검사를 수행하지 않습니다. Pod가 활동성 프로브에 응답하지 못하는 경우 Kubernetes는 결국 해당 Pod를 종료하고 일정을 다시 조정할 수 있습니다. 따라서 Kubernetes의 프로브와 Orleans의 프로브는 상호 보완적입니다.

권장되는 방법은 Kubernetes에서 애플리케이션이 의도한 대로 수행되고 있는지 간단한 로컬 전용 검사를 수행하는 활동성 프로브를 구성하는 것입니다. 이러한 프로브는 런타임 오류 또는 다른 가능성이 낮은 이벤트로 인해 완전 동결이 있는 경우 프로세스를 종료하는 역할을 합니다.

리소스 할당량

Kubernetes는 운영 체제와 함께 작동하여 리소스 할당량을 구현합니다. 이렇게 하면 CPU 및 메모리 예약이나 한도를 적용할 수 있습니다. 대화형 로드를 제공하는 기본 애플리케이션의 경우 필요한 경우가 아니면 제한적인 한도를 구현하지 않는 것이 좋습니다. 요청과 한도는 의미와 구현 위치가 크게 다르다는 점에 유의해야 합니다. 요청 또는 한도를 설정하기 전에 시간을 내어 구현 및 적용 방법을 자세히 이해합니다. 예를 들어 Kubernetes, Linux 커널 및 모니터링 시스템 간에 메모리를 균일하게 측정할 수 없습니다. CPU 할당량은 예상한 방식으로 적용되지 않을 수 있습니다.

문제 해결

Pod 충돌, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined 관련 오류

전체 예외 메시지:

Unhandled exception. k8s.Exceptions.KubeConfigException: unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
at k8s.KubernetesClientConfiguration.InClusterConfig()
  • KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT 환경 변수가 Pod 내에 설정되어 있는지 확인합니다. kubectl exec -it <pod_name> /bin/bash -c env 명령을 실행하여 확인할 수 있습니다.
  • Kubernetes deployment.yaml에서 automountServiceAccountTokentrue로 설정되어 있는지 확인합니다. 자세한 내용은 Pod에 대한 서비스 계정 구성을 참조하세요.