Настройка драйвера CSI хранилища секретов для включения контроллера объекта ingress NGINX с протоколом TLS
В этой статье описывается процесс защиты контроллера объекта ingress NGINX с протоколом TLS, кластером Службы Azure Kubernetes (AKS) и экземпляром Azure Key Vault (AKV). Дополнительные сведения см. в статье TLS в Kubernetes.
Сертификат TLS ingress можно импортировать в кластер с помощью одного из следующих методов:
- Приложение: манифест развертывания приложения объявляет и подключает том поставщика. Только при развертывании приложения сертификат, доступный в кластере. При удалении приложения секрет также удаляется. Этот сценарий подходит группам разработчиков, отвечающим за инфраструктуру безопасности приложения и ее интеграцию с кластером.
- Контроллер входящего трафика: развертывание входящего трафика изменяется для объявления и подключения тома поставщика. Секрет импортируется при создании модулей pod входящего трафика. У модулей pod приложения нет доступа к сертификату TLS. В этом случае реализован сценарий, в котором одна команда (например, ИТ) администрирует и создает компоненты инфраструктуры и сети (включая сертификаты HTTPS TLS), а другие команды управляют жизненным циклом приложения.
Необходимые компоненты
- Если у вас нет подписки Azure, создайте бесплатную учетную запись, прежде чем приступить к работе.
- Прежде чем приступать к работе, убедитесь, что версия Azure CLI > =
2.30.0
, или установите последнюю версию. - Кластер AKS с настроенным драйвером CSI хранилища секретов.
- Экземпляр Azure Key Vault.
Создание сертификата TLS
Создайте сертификат TLS с помощью следующей команды.
export CERT_NAME=aks-ingress-cert openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -out aks-ingress-tls.crt \ -keyout aks-ingress-tls.key \ -subj "/CN=demo.azure.com/O=aks-ingress-tls"
Импорт сертификата в AKV
Экспортируйте сертификат в PFX-файл с помощью следующей команды.
export AKV_NAME="[YOUR AKV NAME]" openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out $CERT_NAME.pfx # skip Password prompt
Импортируйте сертификат с помощью
az keyvault certificate import
команды.az keyvault certificate import --vault-name $AKV_NAME --name $CERT_NAME --file $CERT_NAME.pfx
Развертывание SecretProviderClass
Экспортируйте новое пространство имен с помощью следующей команды.
export NAMESPACE=ingress-basic
Создайте пространство имен с помощью
kubectl create namespace
команды.kubectl create namespace $NAMESPACE
Выберите метод передачи удостоверения доступа и настройте соответствующим образом YAML-файл SecretProviderClass.
- Обязательно используйте
objectType=secret
— единственный способ получения закрытого ключа и сертификата из AKV. - Задайте значение
kubernetes.io/tls
для параметраtype
в разделеsecretObjects
.
Вот пример класс SecretProviderClass:
apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-tls spec: provider: azure secretObjects: # secretObjects defines the desired state of synced K8s secret objects - secretName: ingress-tls-csi type: kubernetes.io/tls data: - objectName: $CERT_NAME key: tls.key - objectName: $CERT_NAME key: tls.crt parameters: usePodIdentity: "false" useVMManagedIdentity: "true" userAssignedIdentityID: <client id> keyvaultName: $AKV_NAME # the name of the AKV instance objects: | array: - | objectName: $CERT_NAME objectType: secret tenantId: $TENANT_ID # the tenant ID of the AKV instance
- Обязательно используйте
Примените SecretProviderClass к кластеру Kubernetes с помощью
kubectl apply
команды.kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
Развертывание контроллера объекта ingress
Добавление официального репозитория диаграммы входящего трафика
Добавьте официальный репозиторий диаграмм входящего трафика с помощью следующих
helm
команд.helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update
Настройка и развертывание объекта ingress NGINX
В зависимости от сценария можно привязать сертификат к приложению или к контроллеру входящего трафика. Выполните приведенные ниже инструкции в соответствии с выбранным вами вариантом.
Привязка сертификата к приложению
Привязите сертификат к приложению с помощью
helm install
команды. Развертывание приложения ссылается на поставщик Azure Key Vault драйвера CSI хранилища секретов.helm install ingress-nginx/ingress-nginx --generate-name \ --namespace $NAMESPACE \ --set controller.replicaCount=2 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux
Привязка сертификата к контроллеру объекта ingress
Привязите сертификат к контроллеру входящего трафика с помощью
helm install
команды. Развертывание контроллера входящего трафика ссылается на поставщик Azure Key Vault драйвера CSI хранилища секретов.Примечание.
Если в качестве метода доступа не используется управляемое пользователем удостоверение Microsoft Entra pod, удалите строку с
--set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME
.Кроме того, привязка SecretProviderClass к pod требуется для подключения драйвера CSI хранилища секретов для его подключения и создания секрета Kubernetes. См. раздел "Синхронизация подключенного содержимого с помощью секрета Kubernetes".
helm install ingress-nginx/ingress-nginx --generate-name \ --namespace $NAMESPACE \ --set controller.replicaCount=2 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \ --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \ --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME \ -f - <<EOF controller: extraVolumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" extraVolumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true EOF
Убедитесь, что секрет Kubernetes был создан с помощью
kubectl get secret
команды.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Развертывание приложения
Опять же, инструкции немного изменяются в зависимости от вашего сценария. Следуйте инструкциям, соответствующим выбранному сценарию.
Развертывание приложения с использованием ссылки на приложение
Создайте файл
aks-helloworld-one.yaml
со следующим содержимым:apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-one spec: replicas: 1 selector: matchLabels: app: aks-helloworld-one template: metadata: labels: app: aks-helloworld-one spec: containers: - name: aks-helloworld-one image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "Welcome to Azure Kubernetes Service (AKS)" volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-one spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-one
Создайте файл
aks-helloworld-two.yaml
со следующим содержимым:apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-two spec: replicas: 1 selector: matchLabels: app: aks-helloworld-two template: metadata: labels: app: aks-helloworld-two spec: containers: - name: aks-helloworld-two image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "AKS Ingress Demo" volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-two spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-two
Примените файлы YAML к кластеру
kubectl apply
с помощью команды.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Убедитесь, что секрет Kubernetes был создан с помощью
kubectl get secret
команды.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Развертывание приложения с использованием ссылки на контроллер объекта ingress
Создайте файл
aks-helloworld-one.yaml
со следующим содержимым:apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-one spec: replicas: 1 selector: matchLabels: app: aks-helloworld-one template: metadata: labels: app: aks-helloworld-one spec: containers: - name: aks-helloworld-one image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "Welcome to Azure Kubernetes Service (AKS)" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-one spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-one
Создайте файл
aks-helloworld-two.yaml
со следующим содержимым:apiVersion: apps/v1 kind: Deployment metadata: name: aks-helloworld-two spec: replicas: 1 selector: matchLabels: app: aks-helloworld-two template: metadata: labels: app: aks-helloworld-two spec: containers: - name: aks-helloworld-two image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 ports: - containerPort: 80 env: - name: TITLE value: "AKS Ingress Demo" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-two spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-two
Примените файлы YAML к кластеру
kubectl apply
с помощью команды.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Развертывание ресурса входящего трафика, ссылающегося на секрет
Теперь можно развернуть ресурс входящего трафика Kubernetes, ссылающийся на секрет.
Создайте имя
hello-world-ingress.yaml
файла со следующим содержимым.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-tls annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx tls: - hosts: - demo.azure.com secretName: ingress-tls-csi rules: - host: demo.azure.com http: paths: - path: /hello-world-one(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80 - path: /hello-world-two(/|$)(.*) pathType: Prefix backend: service: name: aks-helloworld-two port: number: 80 - path: /(.*) pathType: Prefix backend: service: name: aks-helloworld-one port: number: 80
Запишите
tls
раздел, ссылающийся на секрет, созданный ранее, и примените файл к кластеру с помощьюkubectl apply
команды.kubectl apply -f hello-world-ingress.yaml -n $NAMESPACE
Получение внешнего IP-адреса контроллера объекта ingress
Получите внешний IP-адрес для контроллера входящего трафика с помощью
kubectl get service
команды.kubectl get service --namespace $NAMESPACE --selector app.kubernetes.io/name=ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-1588032400-controller LoadBalancer 10.0.255.157 EXTERNAL_IP 80:31293/TCP,443:31265/TCP 19m nginx-ingress-1588032400-default-backend ClusterIP 10.0.223.214 <none> 80/TCP 19m
Проверка входящего трафика, защищенного с помощью TLS
Убедитесь, что вход правильно настроен с помощью TLS с помощью следующей
curl
команды. Убедитесь, что вы используете внешний IP-адрес из предыдущего шага.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com
Так как другой путь не был предоставлен с адресом, контроллер входящего трафика по умолчанию соответствует маршруту / . Первое демонстрационное приложение возвращается, как показано в следующем сокращенном примере выходных данных:
[...] <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="/static/default.css"> <title>Welcome to Azure Kubernetes Service (AKS)</title> [...]
Параметр -v в
curl
команде выводит подробные сведения, включая полученный сертификат TLS. На полпути выходных данных curl можно проверить использование собственного сертификата TLS. При использовании параметра -k по-прежнему загружается страница, несмотря на то что используется самозаверяющий сертификат. В следующем примере показан издатель: CN=demo.azure.com; Использовался сертификат O=aks-ingress-tls :[...] * Server certificate: * subject: CN=demo.azure.com; O=aks-ingress-tls * start date: Oct 22 22:13:54 2021 GMT * expire date: Oct 22 22:13:54 2022 GMT * issuer: CN=demo.azure.com; O=aks-ingress-tls * SSL certificate verify result: self signed certificate (18), continuing anyway. [...]
Добавьте в адрес /hello-world-two путь, например
https://demo.azure.com/hello-world-two
, и убедитесь, что второе демонстрационное приложение настроено правильно.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com/hello-world-two
Второе демонстрационное приложение с настраиваемым заголовком возвращается, как показано в следующем сокращенном примере выходных данных:
[...] <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <link rel="stylesheet" type="text/css" href="/static/default.css"> <title>AKS Ingress Demo</title> [...]
Azure Kubernetes Service