Hospedagem Kubernetes
O Kubernetes é uma escolha popular para hospedagem Orleans de aplicativos. Orleans será executado no Kubernetes sem configuração específica, no entanto, também pode tirar proveito do conhecimento extra que a plataforma de hospedagem pode fornecer.
O Microsoft.Orleans.Hosting.Kubernetes
pacote adiciona integração para hospedar um Orleans aplicativo em um cluster Kubernetes. O pacote fornece um método de extensão, UseKubernetesHosting, que executa as seguintes ações:
- SiloOptions.SiloName está definido como o nome do pod.
- EndpointOptions.AdvertisedIPAddress está definido para o IP do pod.
- EndpointOptions.SiloListeningEndpoint & EndpointOptions.GatewayListeningEndpoint são configurados para ouvir em qualquer endereço, com o configurado SiloPort e GatewayPort. Os valores de porta padrão de
11111
e30000
são usados se nenhum valor for definido explicitamente). - ClusterOptions.ServiceId é definido como o valor do rótulo do pod com o nome
orleans/serviceId
. - ClusterOptions.ClusterId é definido como o valor do rótulo do pod com o nome
orleans/clusterId
. - No início do processo de inicialização, o silo sondará o Kubernetes para descobrir quais silos não têm pods correspondentes e marcar esses silos como mortos.
- O mesmo processo ocorrerá em tempo de execução para um subconjunto de todos os silos, para remover a carga no servidor de API do Kubernetes. Por padrão, 2 silos no cluster observarão o Kubernetes.
Observe que o pacote de hospedagem do Kubernetes não usa o Kubernetes para clustering. Para clustering, ainda é necessário um provedor de clustering separado. Para obter mais informações sobre como configurar clustering, consulte a documentação de configuração do servidor.
Essa funcionalidade impõe alguns requisitos sobre como o serviço é implantado:
- Os nomes dos silos devem corresponder aos nomes dos pods.
- As vagens devem ter um
orleans/serviceId
rótulo queorleans/clusterId
corresponda ao siloServiceId
eClusterId
. O método acima mencionado propagará esses rótulos para as opções correspondentes em Orleans variáveis de ambiente. - Os pods devem ter as seguintes variáveis de ambiente definidas:
POD_NAME
,POD_NAMESPACE
,POD_IP
,ORLEANS_SERVICE_ID
,ORLEANS_CLUSTER_ID
.
O exemplo a seguir mostra como configurar esses rótulos e variáveis de ambiente corretamente:
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
Para clusters habilitados para RBAC, a conta de serviço do Kubernetes para os pods também pode precisar receber o acesso necessário:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: orleans-hosting
rules:
- apiGroups: [ "" ]
resources: ["pods"]
verbs: ["get", "watch", "list", "delete", "patch"]
---
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: ''
Vivacidade, prontidão e sondas de arranque
O Kubernetes pode sondar pods para determinar a integridade de um serviço. Para obter mais informações, consulte Configurar sondas de animação, prontidão e inicialização na documentação do Kubernetes.
Orleans Usa um protocolo de associação de cluster para detetar e recuperar prontamente de um processo ou falhas de rede. Cada nó monitora um subconjunto de outros nós, enviando sondas periódicas. Se um nó não responder a várias sondas sucessivas de vários outros nós, ele será removido à força do cluster. Quando um nó com falha descobre que foi removido, ele é encerrado imediatamente. O Kubernetes reiniciará o processo encerrado e tentará ingressar novamente no cluster.
As sondas do Kubernetes podem ajudar a determinar se um processo em um pod está em execução e não está preso em um estado zumbi. Os testes não verificam a conectividade ou a capacidade de resposta entre pods nem realizam verificações de funcionalidade no nível do aplicativo. Se um pod não responder a uma sonda de liveness, o Kubernetes pode eventualmente encerrar esse pod e reprogramá-lo. As sondas Kubernetes e Orleansas sondas são, portanto, complementares.
A abordagem recomendada é configurar Sondas Liveness no Kubernetes, que executam uma verificação local simples de que o aplicativo está funcionando conforme o esperado. Essas sondas servem para encerrar o processo se houver um congelamento total, por exemplo, devido a uma falha de tempo de execução ou outro evento improvável.
Quotas de recursos
O Kubernetes trabalha em conjunto com o sistema operacional para implementar cotas de recursos. Isso permite que as reservas e/ou limites de CPU e memória sejam aplicados. Para um aplicativo principal que esteja servindo carga interativa, recomendamos não implementar limites restritivos, a menos que necessário. É importante notar que os pedidos e os limites são substancialmente diferentes no seu significado e no local onde são implementados. Antes de definir solicitações ou limites, reserve um tempo para obter uma compreensão detalhada de como eles são implementados e aplicados. Por exemplo, a memória pode não ser medida uniformemente entre o Kubernetes, o kernel Linux e seu sistema de monitoramento. As cotas de CPU podem não ser aplicadas da maneira esperada.
Resolução de Problemas
Pods caem, reclamando que KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
Mensagem de exceção completa:
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()
- Verifique se
KUBERNETES_SERVICE_HOST
as variáveis deKUBERNETES_SERVICE_PORT
ambiente estão definidas dentro do seu Pod. Você pode verificar executando o seguinte comandokubectl exec -it <pod_name> /bin/bash -c env
. - Certifique-se de definir como
automountServiceAccountToken
true no seu Kubernetesdeployment.yaml
. Para obter mais informações, consulte Configurar contas de serviço para pods