> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/docs.facephi-pt-br/sdks/backend-sdk/voice/installation/kubernetes_deployment.md).

# Implantação em Kubernetes

## 1. Introdução

A seguir, especificamos tudo o que é necessário para instalar **Facephi Voice Service** em um ambiente Kubernetes.

## 2. Implantação manual

### 2.1 Introdução

O serviço Phivox pode ser implantado no Kubernetes com **kubectl**:

```bash
kubectl apply -f manifest.yaml
```

Usando um arquivo *manifest.yaml* semelhante a este:

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: facephi-voice-service
---

apiVersion: v1
kind: Secret
metadata:
  name: voice-license-secret
  namespace: facephi-voice-service
stringData:
  stringData:
  config.cfg: |-
    {
      CONFIG_DIR=<provided by facephi>
      LICENSE_TYPE=<provided by facephi>
      LICENSE_BEHAVIOUR=<provided by facephi>
      LICENSE_ID=<provided by facephi>
      LICENSE_DATA=<provided by facephi>
      LICENSE_KEY=<provided by facephi>
    }
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: voice-service-deployment
  namespace: facephi-voice-service
spec:
  selector:
    matchLabels:
      name: facephi-voice-service
  template:
    metadata:
      labels:
        name: facephi-voice-service
    spec:
      volumes:
        - name: config-volume
          secret:
            secretName: voice-license-secret
            defaultMode: 420
      containers:
        - name: facephi-voice-service-container-name
          # Use o nome e a Versão da sua imagem
          image: >-
            facephicorp.jfrog.io/docker-pro-fphi/facephi-voice-service:$VERSION
          env:
            # Proteção opcional de JWT
            # - name: FACEPHI_VOICE_REST_AUTH_ENABLED
            #   value: "true"
            # - name: FACEPHI_VOICE_REST_AUTH_JWT_SECRET
            #   value: "shared-secret"
            # - name: FACEPHI_VOICE_REST_AUTH_ACCEPT_AUTHORIZATION_HEADER
            #   value: "true"
            # - name: FACEPHI_VOICE_REST_AUTH_ACCEPT_API_KEY_HEADER
            #   value: "true"
            # - name: FACEPHI_VOICE_REST_AUTH_API_KEY_HEADER_NAME
            #   value: "x-api-key"
          ports:
            - name: http
              containerPort: 6982
              protocol: TCP
          resources:
            limits:
              cpu: '8'
              memory: 8Gi
            requests:
              cpu: 500m
              memory: 3Gi
          volumeMounts:
            - name: config-volume
              readOnly: true
              mountPath: /service/config/config.cfg
              subPath: config.cfg
          livenessProbe:
            httpGet:
              path: /api/v1/health
              port: 6982
              scheme: HTTP
            initialDelaySeconds: 10
            timeoutSeconds: 5
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /api/v1/health
              port: 6982
              scheme: HTTP
            initialDelaySeconds: 15
            timeoutSeconds: 5
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      terminationGracePeriodSeconds: 60
---

apiVersion: v1
kind: Service
metadata:
  name: voice-service
  namespace: facephi-voice-service
spec:
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 6982
  type: ClusterIP
---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: voice-ingress
  namespace: facephi-voice-service
spec:
  ingressClassName: kong
  rules:
    - http:
        paths:
          - path: /api(/v1)?/(.*)
            pathType: Prefix
            backend:
              service:
                name: voice-service
                port:
                  number: 80
---
```

É importante ter feito login previamente no Artifactory ou obter a imagem **facephicorp.jfrog.io/docker-pro-fphi/facephi-voice-service** e armazená-la em um repositório de imagens Docker de onde o cluster possa baixá-la.

### 2.2 Volumes

Você deve adicionar o volume com o arquivo de configuração para que o serviço funcione corretamente; esse arquivo de configuração contém as informações da Licença e a configuração do serviço. Por padrão, o caminho em que o arquivo de configuração é armazenado é `/service/config/config.cfg`.

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: config-secret
  namespace: facephi-voice-service
stringData:
  config.cfg: |-
    {
      CONFIG_DIR=<provided by facephi>
      LICENSE_TYPE=<provided by facephi>
      LICENSE_BEHAVIOUR=<provided by facephi>
      LICENSE_ID=<provided by facephi>
      LICENSE_DATA=<provided by facephi>
      LICENSE_KEY=<provided by facephi>
    }
```

Depois que esse secret for criado, o deployment associará o volume no caminho correspondente com as seguintes linhas:

```yaml
...
spec:
  ...
  template:
    ...
    spec:
      volumes:
        - name: config-volume
          secret:
            secretName: config-secret
            defaultMode: 420
        ...
      containers:
        ...
        - volumeMounts:
            - name: config-volume
              readOnly: true
              mountPath: /service/config/config.cfg
              subPath: config.cfg
```

`spec.volumes[0].secret.secretName` busca no namespace o secret gerado previamente e o armazena em um volume com o nome `config-volume`. Ao montar o volume `config-volume`, o Secret associado é buscado, e `mountPath` é definido com o caminho onde o arquivo é armazenado; além disso, podemos especificar um objeto específico do secret por meio de `subPath`, neste caso a chave `config.cfg`.

Quando a autenticação JWT está habilitada, `GET /api/v1/health` e `GET /api/v1/version` continuam públicos e os endpoints protegidos exigem um JWT válido. As configurações de inicialização do JWT não são expostas por meio de `GET /api/v1/config` nem podem ser atualizadas por meio de `POST /api/v1/config`.

### 2.3 Recursos

Após executar os testes de desempenho, foram obtidos os seguintes resultados:

* Para **Enrollment** com **três áudios** (`/api/v1/enrollment/`):

| CPU   | Memória | Tempo médio |
| ----- | ------- | ----------- |
| 4096m | 10Gi    | 2511 ms     |
| 8192m | 10Gi    | 1407 ms     |

* Para **Authentication** (`/api/v1/authentication/`):

| CPU   | Memória | Tempo médio |
| ----- | ------- | ----------- |
| 4096m | 10Gi    | 240 ms      |
| 8192m | 10Gi    | 220 ms      |

Com estes testes, estabelece-se a seguinte configuração em nível de requests e limits.

```yaml
spec:
  ...
  template:
    ...
    spec:
      ...
      containers:
        ...
        - resources
            limits:
              cpu: 4096m  # 4 núcleos
              memory: 8Gi
            requests:
              cpu: 500m # 0.5 núcleos
              memory: 3Gi
```

### 2.4 Serviço

#### 2.4.1 LoadBalancer

Levamos em consideração que configuraremos um LoadBalancer com Kong à frente para acessar o Facephi Voice Service. Observe que o serviço é exposto na porta `80` e aponta para o Pod na porta `6982`.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: facephi-voice-service
  namespace: facephi-voice-service
spec:
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 6982
  selector:
    name: facephi-voice-service
  type: ClusterIP
```

### 2.5 Ingress

Configuramos um Ingress à frente para redirecionar as requisições do Kong ao serviço dentro do Pod que expusemos anteriormente na porta 80.

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: facephi-voice-service
  namespace: facephi-voice-service
spec:
  ingressClassName: kong
  rules:
    - http:
        paths:
          - path: /api(/v1)?/(.*)
            pathType: Prefix
            backend:
              service:
                name: facephi-voice-service
                port:
                  number: 80
```

## 3 Tipos de instância

Os tipos de instância recomendados para usar o Facephi Voice Service em nível de produção seriam os seguintes, onde são mostrados os Pods do Facephi Voice Service que cabem de acordo com o tipo de instância utilizado.

| Tipo de instância | CPU | Memória | Capacidade de Pods do serviço |
| ----------------- | --- | ------- | ----------------------------- |
| c5.xlarge         | 4   | 8       | 2                             |
| c5.2xlarge        | 8   | 16      | 4                             |
| c5.4xlarge        | 16  | 32      | 9                             |
