Поделиться через


Безопасный доступ контейнеров к ресурсам для рабочих нагрузок Службы Azure Kubernetes (AKS) с использованием встроенных средств безопасности Linux

В этой статье вы узнаете, как обеспечить безопасный доступ контейнеров к ресурсам для рабочих нагрузок службы Azure Kubernetes Service (AKS) с использованием пользовательских пространств имен, AppArmor и seccomp, встроенных функций безопасности Linux.

Общие сведения о безопасности доступа к контейнерам

Подобно предоставлению пользователям или группам наименьшего количества требуемых привилегий, контейнеры должны быть ограничены только необходимыми действиями и процессами. Чтобы свести к минимуму риск атак, избегайте настройки приложений и контейнеров, которые требуют повышенных привилегий или корневого доступа.

Встроенные контексты безопасности подов в Kubernetes можно использовать для определения дополнительных разрешений, таких как пользователь или группа, от имени которых запускать, какие возможности Linux предоставить, или настройка в манифесте пода. Другие советы см. в разделе Secure pod access to resources (Обеспечение безопасного доступа pod к ресурсам).

Чтобы улучшить изоляцию хоста и уменьшить боковое перемещение в Linux, можно использовать пространства имен пользователей. Для более детального управления действиями контейнера можно использовать встроенные функции безопасности Linux, такие как AppArmor и seccomp. Эти функции помогают ограничить действия, которые контейнеры могут выполнять, определяя функции безопасности Linux на уровне узла и реализуя их с помощью манифеста pod.

Встроенные функции безопасности Linux доступны только на узлах и POD под управлением Linux.

Примечание.

В настоящее время среды Kubernetes небезопасны для враждебного многопользовательского использования. Другие функции безопасности, такие как Microsoft Defender для контейнеров, AppArmor, seccomp, пространства имен пользователей, допуск безопасности Pod или Kubernetes Role-Based контроль доступа (RBAC) для узлов, эффективно блокируют эксплойты.

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

Для таких типов враждебных мультитенантных рабочих нагрузок следует использовать физически изолированные кластеры.

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

  • Существующий кластер AKS. Если у вас нет кластера, создайте его с помощью Azure CLI, Azure PowerShell или портала Azure.
  • Минимальная версия Kubernetes 1.33 для узлов управления и рабочих узлов. Если вы не используете Kubernetes версии 1.33 или более поздней, необходимо обновить версию Kubernetes.
  • Рабочие узлы, работающие на Azure Linux 3.0 или Ubuntu 24.04, чтобы гарантировать соответствие минимальным требованиям к стеку для активации пространств имен пользователей. Если вам нужно обновить версию операционной системы (ОС), ознакомьтесь с обновлением версии ОС.

Ограничения в пространствах имен пользователей

Общие сведения о пространствах имен пользователей

Модули pod Linux выполняются с помощью нескольких пространств имен по умолчанию: сетевые пространства имен для изоляции сетевого удостоверения и пространства имен PID для изоляции процессов. Пространство имен пользователя (user_namespace) изолирует пользователей внутри контейнера от пользователей на узле. Он также ограничивает область возможностей и взаимодействие pod с остальной частью системы.

Идентификаторы пользовательского интерфейса и GID внутри контейнера сопоставляются с непривилегированных пользователей на узле, поэтому все взаимодействие с остальными узлами происходит так, как эти непривилегированные uiD и GID. Например, корневой каталог в контейнере (UID 0) можно сопоставить с пользователем 65536 на узле. Kubernetes создает сопоставление, чтобы гарантировать, что он не перекрывается с другими модулями pod с помощью пространств имен пользователей в системе.

Реализация Kubernetes имеет некоторые ключевые преимущества. Дополнительные сведения см. в документации по пространствам имен пользователей Kubernetes.

Включить пространства имен пользователей

  1. Создайте файл mypod.yaml и скопируйте в него следующий манифест. Чтобы использовать пространства имен пользователей, yamL должен иметь поле hostUsers: false.

    apiVersion: v1
    kind: Pod
    metadata:
      name: userns
    spec:
      hostUsers: false
      containers:
      - name: shell
        command: ["sleep", "infinity"]
        image: debian
    
  2. Разверните приложение с помощью kubectl apply команды и укажите имя манифеста YAML.

    kubectl apply -f mypod.yaml
    
  3. Проверьте состояние развернутых подов с помощью команды kubectl get pods.

    kubectl get pods
    
  4. Выполните в pod с помощью команды kubectl exec.

    kubectl exec -ti userns -- bash
    
  5. В модуле pod проверьте /proc/self/uid_map следующую команду:

    cat /proc/self/uid_map
    

    Выходные данные должны содержать 65536 в последнем столбце. Рассмотрим пример.

    0  833617920      65536
    

    Это вывод указывает, что root внутри контейнера (UID 0) сопоставляется с пользователем 65536 на хосте.

Уязвимости и опасности (CVEs), устраненные пространствами имен пользователей

В следующей таблице описаны некоторые распространенные уязвимости и уязвимости (CVEs), которые частично или полностью устранены с помощью user_namespaces:

CVE Оценка серьезности Уровень серьезности
CVE-2019-5736 8.6 High
CVE 2024-21262 8.6 High
CVE 2022-0492 7.8 High
CVE-2021-25741 8.1 / 8.8 Высокий / высокий
CVE-2017-1002101 9.6 / 8.8 Критический / высокий

Помните, что этот список не является исчерпывающим. Дополнительные сведения см. в статье Kubernetes версии 1.33: пространства имен пользователей, включенные по умолчанию.

Предварительные требования для AppArmor

Примечание.

Azure Linux 3.0 поддерживает AppArmor, начиная с выпуска VHD от 7 ноября 2025 г.

Обзор AppArmor

Чтобы ограничить действия контейнеров, можно использовать модуль безопасности ядра Linux AppArmor. AppArmor доступен как часть базовой операционной системы узла AKS (OS) и включен по умолчанию. Вы можете создавать профили AppArmor, ограничивающие операции чтения, записи или выполнения действий, а также системные функции, такие как подключение файловых систем. Профили AppArmor по умолчанию ограничивают доступ к различным /proc расположениям и /sys предоставляют средства для логического изоляции контейнеров от базового узла. AppArmor работает с любыми приложениями под управлением Linux, а не только с группами pod Kubernetes.

Примечание.

До версии 1.30 Kubernetes, AppArmor задавался с помощью аннотаций. Начиная с версии 1.30, AppArmor указывается через securityContext поле в спецификации pod. Дополнительные сведения см. в документации по AppArmor Kubernetes.

Профили AppArmor, использующиеся в кластере AKS для ограничения действий контейнера

Защита модулей pod с помощью AppArmor

Профили AppArmor можно указать на уровне pod или контейнера. Профиль AppArmor контейнера имеет приоритет над профилем pod AppArmor. Если ни один из них не указан, контейнер работает без ограничений. Дополнительные сведения о профилях AppArmor см. в документации по защите Pod с помощью AppArmor Kubernetes.

Настройка пользовательского профиля AppArmor

В следующем примере создается профиль, который предотвращает запись в файлы изнутри контейнера.

  1. Подключитесь к узлу AKS по протоколу SSH.

  2. Создайте файл с именем deny-write.profile и вставьте следующее содержимое:

    #include <tunables/global>
    
    profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
      #include <abstractions/base>
    
      file,
    
      # Deny all file writes.
      deny /** w,
    }
    
  3. Загрузите профиль AppArmor на узел.

    # This example assumes that node names match host names, and are reachable via SSH.
    NODES=($( kubectl get node -o jsonpath='{.items[*].status.addresses[?(.type == "Hostname")].address}' ))
    
    for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q <<EOF
    #include <tunables/global>
    
    profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
      #include <abstractions/base>
    
      file,
    
      # Deny all file writes.
      deny /** w,
    }
    EOF'
    done
    

Развертывание модуля pod с помощью пользовательского профиля AppArmor

  1. Разверните модуль pod Hello AppArmor с профилем запрета на запись.

    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-apparmor
    spec:
      securityContext:
        appArmorProfile:
          type: Localhost
          localhostProfile: k8s-apparmor-example-deny-write
      containers:
      - name: hello
        image: busybox:1.28
        command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    
  2. Примените манифест pod с помощью kubectl apply команды.

    kubectl apply -f hello-apparmor.yaml
    
  3. Exec в pod и проверьте, что контейнер запущен с профилем AppArmor.

    kubectl exec hello-apparmor -- cat /proc/1/attr/current
    

    Выходные данные должны отображать используемый профиль AppArmor. Рассмотрим пример.

    k8s-apparmor-example-deny-write (enforce)
    

Предварительные требования seccomp

Регистрация флага компонента KubeletDefaultSeccompProfilePreview

Внимание

Предварительные версии функций AKS доступны на условиях самообслуживания с возможностью подключения по выбору. Предварительные версии предоставляются "как есть" и "при наличии". На них не распространяются соглашения об уровне обслуживания и ограниченная гарантия. Предварительные версии AKS предоставляются с частичной клиентской поддержкой на основе принципа наилучших усилий. Следовательно, эти функции не предназначены для использования в рабочей среде. Дополнительные сведения доступны в следующих статьях поддержки.

  1. KubeletDefaultSeccompProfilePreview Зарегистрируйте флаг компонента с помощью az feature register команды.

    az feature register --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    

    Через несколько минут отобразится состояние Registered (Зарегистрировано).

  2. Проверьте состояние регистрации с помощью az feature show команды.

    az feature show --namespace "Microsoft.ContainerService" --name "KubeletDefaultSeccompProfilePreview"
    
  3. Когда состояние отражает зарегистрировано, обновите регистрацию поставщика ресурсов Microsoft.ContainerService с помощью az provider register команды.

    az provider register --namespace Microsoft.ContainerService
    

Ограничения Seccomp

  • AKS поддерживает только профили seccomp по умолчанию (RuntimeDefault и Unconfined). Пользовательские профили seccomp не поддерживаются.
  • SeccompDefault не поддерживается для пулов узлов Windows.

Обзор профилей seccomp по умолчанию (предварительная версия)

Хотя AppArmor работает для любого приложения Linux, seccomp (или безопасные вычисления) работает на уровне процесса. Seccomp также является модулем безопасности ядра Linux. Среда выполнения, используемая containerd узлами AKS, обеспечивает встроенную поддержку seccomp. С помощью seccomp можно ограничить системные вызовы контейнера. Seccomp устанавливает дополнительный уровень защиты от распространенных уязвимостей вызова системы, эксплуатируемых вредоносными субъектами, и позволяет указать профиль по умолчанию для всех рабочих нагрузок в узле.

Вы можете применить профили seccomp по умолчанию с помощью пользовательских конфигураций узлов при создании пула узлов Linux. AKS поддерживает RuntimeDefault и Unconfined значения. Для некоторых рабочих нагрузок может потребоваться меньшее количество ограничений на системные вызовы по сравнению с другими. Это означает, что они могут завершиться ошибкой во время выполнения с использованием профиля RuntimeDefault. Чтобы устранить такой сбой, можно специфицировать профиль Unconfined. Если для рабочей нагрузки требуется пользовательский профиль, см. Настройка пользовательского профиля seccomp.

Ограничение вызовов системы контейнеров с помощью seccomp

  1. Выполните действия, чтобы применить профиль seccomp в конфигурации kubelet , указав "seccompDefault": "RuntimeDefault".
  2. Подключитесь к узлу.
  3. Убедитесь, что конфигурация применена к узлам.

Устранение сбоев рабочей нагрузки с помощью seccomp

Если параметр SeccompDefault включен, профиль seccomp среды выполнения контейнеров используется по умолчанию для всех рабочих нагрузок, запланированных на узле, что может привести к сбоям из-за заблокированных системных вызовов. Если возникает сбой рабочей нагрузки, могут появиться такие ошибки, как:

  • Рабочая нагрузка неожиданно прекращается после включения функции с ошибкой "отказано в разрешении".
  • Сообщения об ошибках Seccomp также можно просмотреть в аудите или системном журнале, заменив SCMP_ACT_ERRNO на SCMP_ACT_LOG в профиле по умолчанию.

При возникновении этих ошибок рекомендуется изменить профиль seccomp на Unconfined. Unconfined не устанавливает ограничений на syscalls, что позволяет выполнять все системные вызовы.

Обзор пользовательских профилей seccomp

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

  • Использование фильтров для указания действий, которые нужно разрешить или запретить.
  • Добавление заметок в манифест YAML модуля pod для связи с фильтром seccomp.

Настройка пользовательского профиля seccomp

Чтобы увидеть seccomp в действии, создайте фильтр, который предотвращает изменение разрешений для файла.

  1. Подключитесь к узлу AKS по протоколу SSH.

  2. Создайте фильтр seccomp с именем /var/lib/kubelet/seccomp/prevent-chmod.

  3. Скопируйте и вставьте следующее содержимое:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "name": "chmod",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "fchmodat",
          "action": "SCMP_ACT_ERRNO"
        },
        {
          "name": "chmodat",
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    

    В версии 1.19 и более поздних версий необходимо настроить следующее:

    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "syscalls": [
        {
          "names": ["chmod","fchmodat","chmodat"],
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }
    
  4. На локальном компьютере создайте манифест pod с именем aks-seccomp.yaml и вставьте следующее содержимое. Этот манифест определяет аннотацию для seccomp.security.alpha.kubernetes.io и ссылается на существующий фильтр prevent-chmod.

    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
      annotations:
        seccomp.security.alpha.kubernetes.io/pod: localhost/prevent-chmod
    spec:
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    

    В версии 1.19 и более поздних версий необходимо настроить следующее:

    apiVersion: v1
    kind: Pod
    metadata:
      name: chmod-prevented
    spec:
      securityContext:
        seccompProfile:
          type: Localhost
          localhostProfile: prevent-chmod
      containers:
      - name: chmod
        image: mcr.microsoft.com/dotnet/runtime-deps:6.0
        command:
          - "chmod"
        args:
         - "777"
         - /etc/hostname
      restartPolicy: Never
    
  5. Разверните пример pod с помощью kubectl apply команды:

    kubectl apply -f ./aks-seccomp.yaml
    
  6. Просмотрите состояние pod с помощью kubectl get pods команды.

    kubectl get pods
    

    В выводе вы должны увидеть, что pod сообщает об ошибке. Команда chmod не запускается фильтром seccomp, как показано в примере выходных данных:

    NAME                      READY     STATUS    RESTARTS   AGE
    chmod-prevented           0/1       Error     0          7s
    

Параметры профиля безопасности Seccomp

Профили безопасности Seccomp — это набор определенных системных вызовов, которые разрешены или ограничены. Большинство сред выполнения контейнеров имеют профиль seccomp по умолчанию, аналогичный, если он не совпадает с используемым Docker. Дополнительные сведения о доступных профилях см. в профилях Docker или containerd по умолчанию seccomp.

AKS использует профиль seccomp по умолчанию для containerd при RuntimeDefault конфигурировании seccomp с помощью пользовательской конфигурации узла.

Заблокированные по умолчанию существенные системные вызовы

Оба Docker и containerd поддерживают списки разрешённых безопасных системных вызовов. При внесении изменений в Docker и контейнере AKS обновляет конфигурацию по умолчанию для сопоставления. Обновления этого списка могут привести к сбою рабочей нагрузки. Сведения об обновлениях выпуска см. в заметках о выпуске AKS.

В следующей таблице перечислены ключевые системные вызовы, которые фактически блокируются, так как они не находятся в разрешённом списке. Этот список не является исчерпывающим. Если для рабочей нагрузки требуется любой из заблокированных системных вызовов, не используйте профиль seccomp RuntimeDefault.

Заблокированный syscall Описание
acct Системный учет, который может позволить контейнерам отключить собственные ограничения ресурсов или учет процессов. Кроме того, заготовка CAP_SYS_PACCT.
add_key Запретить контейнерам использовать ключевое кольцо ядра, которое не поддерживает пространств имен.
bpf Запретить загрузку потенциально постоянных программ bpf в ядро, уже зашитых CAP_SYS_ADMIN.
clock_adjtime Время и дата не пространству имен. Кроме того, заготовка CAP_SYS_TIME.
clock_settime Время и дата не пространству имен. Кроме того, заготовка CAP_SYS_TIME.
clone Запретить клонирование новых пространств имен. Также ограничено флагами CAP_SYS_ADMIN for CLONE_*, за исключением CLONE_NEWUSER.
create_module Запрет манипуляций и функций в модулях ядра. Является устаревшей. Кроме того, заготовка CAP_SYS_MODULE.
delete_module Запрет манипуляций и функций в модулях ядра. Кроме того, заготовка CAP_SYS_MODULE.
finit_module Запрет манипуляций и функций в модулях ядра. Кроме того, заготовка CAP_SYS_MODULE.
get_kernel_syms Запретить извлечение экспортированных символов ядра и модуля. Является устаревшей.
get_mempolicy Syscall, который изменяет память ядра и настройки NUMA. Уже ограждено CAP_SYS_NICE.
init_module Запрет манипуляций и функций в модулях ядра. Кроме того, заготовка CAP_SYS_MODULE.
ioperm Запретить контейнерам изменять уровни привилегий ядра ввода-вывода. Уже ограждено CAP_SYS_RAWIO.
iopl Запретить контейнерам изменять уровни привилегий ядра ввода-вывода. Уже ограждено CAP_SYS_RAWIO.
kcmp Ограничить возможности проверки процесса, уже заблокированные путем удаления CAP_SYS_PTRACE.
kexec_file_load Сестра syscall kexec_load, которая делает то же самое, немного разные аргументы. Кроме того, заготовка CAP_SYS_BOOT.
kexec_load Запретить загрузку нового ядра для последующего выполнения. Кроме того, заготовка CAP_SYS_BOOT.
keyctl Запретить контейнерам использовать ключевое кольцо ядра, которое не поддерживает пространств имен.
lookup_dcookie Трассировка и профилирование syscall, которая может утечка информации на узле. Кроме того, заготовка CAP_SYS_ADMIN.
mbind Syscall, который изменяет память ядра и настройки NUMA. Уже ограждено CAP_SYS_NICE.
mount Запретить монтаж, уже заблокированный CAP_SYS_ADMIN.
move_pages Syscall, который изменяет память ядра и настройки NUMA.
nfsservctl Запретить взаимодействие с управляющей программой ядра nfs. Устаревшее с версии 3.1 Linux.
open_by_handle_at Причина разрыва старого контейнера. Кроме того, заготовка CAP_DAC_READ_SEARCH.
perf_event_open Трассировка и профилирование syscall, которая может утечка информации на узле.
personality Запретить контейнеру включить эмуляцию BSD. Не являясь изначально опасным, плохо протестирован, существует потенциал для уязвимостей в ядре.
pivot_root Запретить pivot_root должно быть привилегированной операцией.
process_vm_readv Ограничить возможности проверки процесса, уже заблокированные путем удаления CAP_SYS_PTRACE.
process_vm_writev Ограничить возможности проверки процесса, уже заблокированные путем удаления CAP_SYS_PTRACE.
ptrace Трассировка или профилирование системных вызовов. Заблокировано в версиях ядра Linux до версии 4.8, чтобы избежать обхода seccomp. Трассировка или профилирование произвольных процессов уже заблокированы путем дроппинга CAP_SYS_PTRACE, так как это может привести к утечке информации на хосте.
query_module Запрет манипуляций и функций в модулях ядра. Является устаревшей.
quotactl Системный параметр квоты, который может позволить контейнерам отключить собственные ограничения ресурсов или учет процессов. Кроме того, заготовка CAP_SYS_ADMIN.
reboot Не позволяйте контейнерам перезагружать хост. Кроме того, заготовка CAP_SYS_BOOT.
request_key Запретить контейнерам использовать ключевое кольцо ядра, которое не поддерживает пространств имен.
set_mempolicy Syscall, который изменяет память ядра и настройки NUMA. Уже ограждено CAP_SYS_NICE.
setns Запретить связывание потока с пространством имен. Кроме того, заготовка CAP_SYS_ADMIN.
settimeofday Время и дата не пространству имен. Кроме того, заготовка CAP_SYS_TIME.
stime Время и дата не пространству имен. Кроме того, заготовка CAP_SYS_TIME.
swapon Запретить переключение запуска и остановки на файл или устройство. Кроме того, заготовка CAP_SYS_ADMIN.
swapoff Запретить переключение запуска и остановки на файл или устройство. Кроме того, заготовка CAP_SYS_ADMIN.
sysfs Устаревший системный вызов (syscall)
_sysctl Устаревший, заменён на /proc/sys.
umount Должна быть привилегированной операцией. Кроме того, заготовка CAP_SYS_ADMIN.
umount2 Должна быть привилегированной операцией. Кроме того, заготовка CAP_SYS_ADMIN.
unshare Запрет клонирования новых пространств имен для процессов. Также регулируется CAP_SYS_ADMIN (за исключением unshare --user).
uselib Старый системный вызов, связанный с общими библиотеками, неиспользуемый в течение длительного времени.
userfaultfd Обработка ошибок страниц пользовательского пространства, в основном необходимая для миграции процессов.
ustat Устаревший системный вызов (syscall)
vm86 Виртуальная машина на базе ядра x86 в реальном режиме. Кроме того, заготовка CAP_SYS_ADMIN.
vm86old Виртуальная машина на базе ядра x86 в реальном режиме. Кроме того, заготовка CAP_SYS_ADMIN.

Дополнительные сведения о защите кластера AKS см. в следующих статьях: