---
title: "Подключение собственного SSL-сертификата к балансировщику в Kubernetes"
description: "Настройка собственного SSL-сертификата для балансировщика Kubernetes. Подключение TLS-секрета, проверка сертификата, обновление и диагностика ошибок. Документация и инструкции по работе с Kubernetes в Timeweb Cloud."
---

> Полный индекс документации для ИИ-агентов: [llms.txt](https://timeweb.cloud/llms.txt).

Балансировщик нагрузки поддерживает использование собственного SSL-сертификата, загруженного из Kubernetes-секрета типа `kubernetes.io/tls`.

Для настройки необходимо создать TLS-секрет с сертификатом и приватным ключом, а затем указать его в аннотациях балансировщика.

> [!NOTE]
> При настройке сертификата через балансировщик нельзя использовать самоподписанные сертификаты. Необходимо использовать сертификат, выпущенный доверенным центром сертификации.

## Создание секрета

Скачайте файлы сертификата. Создайте TLS-секрет в том же неймспейсе, где находится балансировщик:

```bash
kubectl -n <namespace> create secret tls my-app-tls \
  --cert=crt.crt \
  --key=key.key
```

Проверить тип секрета можно командой:

```bash
kubectl -n <namespace> get secret my-app-tls -o yaml
```

В выводе должно присутствовать:

```bash
type: kubernetes.io/tls
```

## Настройка сервиса

Добавьте аннотации для использования собственного сертификата в манифесте балансировщика:

```bash
apiVersion: v1
kind: Service
metadata:
  name: my-app
  annotations:
    k8s.timeweb.cloud/attached-loadbalancer-ssl: "true"
    k8s.timeweb.cloud/attached-loadbalancer-ssl-type: "custom"
    k8s.timeweb.cloud/attached-loadbalancer-ssl-fqdn: "example.com"
    k8s.timeweb.cloud/attached-loadbalancer-ssl-secret-name: "my-app-tls"
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - name: https
      port: 443
      targetPort: 80
      appProtocol: k8s.timeweb.cloud/proto-https
```

Параметры:

-   `k8s.timeweb.cloud/attached-loadbalancer-ssl` — включает использование SSL-сертификата.
    
-   `k8s.timeweb.cloud/attached-loadbalancer-ssl-type` — определяет тип сертификата. Для собственного сертификата используйте значение `custom`.
    
-   `k8s.timeweb.cloud/attached-loadbalancer-ssl-fqdn` — доменное имя, для которого выпущен сертификат.
    
-   `k8s.timeweb.cloud/attached-loadbalancer-ssl-secret-name` — имя TLS-секрета, содержащего сертификат и приватный ключ.
    

Примените изменения:

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

## Проверка сертификата

Проверить сертификат, который использует балансировщик, можно командой:

```bash
echo | openssl s_client \
  -connect example.com:443 \
  -servername example.com \
  2>/dev/null | openssl x509 -noout -subject -issuer -dates
```

Пример успешного результата:

```bash
subject=CN=example.com
issuer=C=BE, O=GlobalSign nv-sa, CN=GlobalSign GCC R6 AlphaSSL CA 2025
```

Также можно проверить HTTPS-соединение через `curl`:

```bash
curl -kv https://example.com
```

В выводе должно присутствовать:

```bash
SSL certificate verify ok.
```

Также в выводе должна быть информация о вашем сертификате:

```bash
subject: CN=example.com
```

Если вместо этого отображается сертификат вида:

```bash
subject: CN=empty
```

— значит, балансировщик не смог применить указанный сертификат и использует сертификат по умолчанию.

## Обновление сертификата

Для замены сертификата обновите существующий секрет:

```bash
kubectl -n <namespace> create secret tls my-app-tls \
  --cert=new.crt \
  --key=new.key \
  --dry-run=client -o yaml | kubectl apply -f -
```

После обновления секрета необходимо запустить повторную настройку балансировщика, изменив любую аннотацию сервиса:

```bash
kubectl -n <namespace> annotate svc my-app \
  k8s.timeweb.cloud/rotate-ts="$(date +%s)" \
  --overwrite
```

После этого CCM повторно прочитает сертификат и обновит его на балансировщике.

## Практический пример

В этом примере настроим собственный SSL-сертификат для тестового приложения Nginx.

Перед началом убедитесь, что у вас есть домен и выпущенный для него сертификат от доверенного центра сертификации.

### Создание неймспейса

Создайте отдельный неймспейс для тестирования:

```bash
kubectl create namespace test-namespace
```

### Создание тестового приложения

Создайте файл `nginx-deployment.yaml`:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: test-namespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-custom-cert-test
  template:
    metadata:
      labels:
        app: nginx-custom-cert-test
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
```

Примените манифест:

```bash
kubectl apply -f nginx-deployment.yaml
```

Убедитесь, что под успешно запущен:

```bash
kubectl get pods -n test-namespace
```

### Создание балансировщика нагрузки

Создайте файл `nginx-loadbalancer.yaml`:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
  namespace: test-namespace
spec:
  type: LoadBalancer
  selector:
    app: nginx-custom-cert-test
  ports:
    - name: https
      port: 443
      targetPort: 80
      appProtocol: k8s.timeweb.cloud/proto-https
```

Примените манифест:

```bash
kubectl apply -f nginx-loadbalancer.yaml
```

Дождитесь появления внешнего IP-адреса:

```bash
kubectl get svc nginx-loadbalancer -n test-namespace -w
```

Пример вывода:

```bash
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)
nginx-loadbalancer   LoadBalancer   10.101.130.253   203.0.113.10    443:31826/TCP
```

### Настройка DNS-записи

Создайте A-запись для домена и направьте ее на внешний IP-адрес балансировщика.

Проверьте, что домен указывает на IP-адрес балансировщика:

```bash
dig +short example.com
```

Результат должен содержать IP-адрес балансировщика.

### Создание TLS-секрета

Создайте TLS-секрет в том же неймспейсе, где находится сервис:

```bash
kubectl -n test-namespace create secret tls my-app-tls \
  --cert=crt.crt \
  --key=key.key
```

Проверьте, что секрет создан корректно:

```bash
kubectl -n test-namespace get secret my-app-tls -o yaml
```

В выводе должно присутствовать:

```shell
type: kubernetes.io/tls
```

При необходимости можно проверить сертификат непосредственно из секрета:

```bash
kubectl -n test-namespace get secret my-app-tls \
  -o jsonpath='{.data.tls\.crt}' \
  | base64 -d \
  | openssl x509 -noout -subject -issuer -dates
```

### Подключение сертификата к балансировщику

Добавьте аннотации для использования собственного сертификата в манифест сервиса `nginx-loadbalancer.yaml`:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
  namespace: test-namespace
  annotations:
    k8s.timeweb.cloud/attached-loadbalancer-ssl: "true"
    k8s.timeweb.cloud/attached-loadbalancer-ssl-type: "custom"
    k8s.timeweb.cloud/attached-loadbalancer-ssl-fqdn: "example.com"
    k8s.timeweb.cloud/attached-loadbalancer-ssl-secret-name: "my-app-tls"
spec:
  type: LoadBalancer
  selector:
    app: nginx-custom-cert-test
  ports:
    - name: https
      port: 443
      targetPort: 80
      appProtocol: k8s.timeweb.cloud/proto-https
```

Примените обновленный манифест:

```bash
kubectl apply -f nginx-loadbalancer.yaml
```

Проверьте настройки сервиса:

```bash
kubectl -n test-namespace get svc nginx-loadbalancer -o yaml
```

В аннотациях должны присутствовать:

```yaml
k8s.timeweb.cloud/attached-loadbalancer-ssl: "true"
k8s.timeweb.cloud/attached-loadbalancer-ssl-type: custom
k8s.timeweb.cloud/attached-loadbalancer-ssl-fqdn: example.com
k8s.timeweb.cloud/attached-loadbalancer-ssl-secret-name: my-app-tls
```

После успешной обработки сертификата появится служебная аннотация:

```bash
k8s.timeweb.cloud/attached-loadbalancer-ssl-cert-hash: ...
```

Это означает, что CCM успешно прочитал сертификат из секрета.

### Проверка работы приложения

Обратитесь к домену в браузере. Если сертификат успешно применен, браузер установит защищенное HTTPS-соединение без предупреждений о недоверенном сертификате.

Также можно проверить доступность приложения с помощью `curl`:

```bash
curl -I https://example.com
```

Успешный ответ означает, что:

-   сертификат загружен на балансировщик;
    
-   HTTPS-соединение устанавливается корректно;
    
-   балансировщик передает запросы в приложение, работающее в Kubernetes.
    

### Удаление тестового окружения

После завершения проверки удалите тестовый неймспейс:

```bash
kubectl delete namespace test-namespace
```

Будут удалены все созданные ресурсы, включая Deployment, Service и TLS-секрет.
