Этот учебник был первоначально опубликован в блоге SigNoz и написан Винаяком Пандеем.
Kubernetes является фактическим лидером среди инструментов оркестровки контейнеров. С ростом популярности разработки на основе микросервисов Kubernetes стал основным инструментом для развертывания и управления крупномасштабными корпоративными приложениями. Однако, несмотря на множество функций, предлагаемых Kubernetes, это сложный инструмент для управления и эксплуатации. Эта статья будет посвящена тому, как настроить журналы аудита Kubernetes, чтобы вы могли иметь записи о событиях, происходящих в вашем кластере.
Что такое журнал аудита Kubernetes?
Если у вас есть опыт работы с Kubernetes, то вы должны знать, что все коммуникации между компонентами Kubernetes и команды, выполняемые пользователями, представляют собой вызовы REST API. Kubernetes API Server — это компонент, который обрабатывает все эти запросы. Поэтому всякий раз, когда вы выполняете команду kubectl, она, по сути, является оберткой для вызова API, сделанного к серверу API.
Журналы аудита Kubernetes записывают все эти вызовы API, сделанные к серверу API. Сюда входят вызовы API различных пользователей и вызовы, сделанные различными компонентами самой Kubernetes. Эти журналы предоставляют много информации, связанной с запросом API, например, время запроса, IP-адрес источника и пользователя, который сделал запрос, тип запроса и ответ, отправленный сервером API.
Зачем нужно настраивать журналы аудита Kubernetes?
Журналы аудита обеспечивают видимость событий, происходящих в кластере Kubernetes, и служат основой для обеспечения безопасности и соответствия нормативным требованиям. Правильно настроенные журналы аудита позволяют быстро выявить любую аномальную активность, происходящую в кластере, например, неудачные попытки входа в систему или попытки получить доступ к конфиденциальным секретам.
Аудит позволяет быстро принимать меры в отношении злонамеренных действий вместо того, чтобы действовать изолированно. Регулярный аудит данных журнала событий также помогает в укреплении кластера и устранении любых ошибок в конфигурации.
Политика аудита Kubernetes
Журналы аудита собираются на основе настроенной политики аудита. Политика аудита определяет, какие события должны быть записаны и какие данные должны быть включены. Правила, настроенные в политике аудита, обрабатываются по порядку, и первое совпадающее правило устанавливает уровень аудита события.
Каждый запрос может быть записан с соответствующим этапом. Ниже перечислены этапы, для которых может быть включена регистрация аудита:
- RequestReceived: Этап для событий, генерируемых, как только обработчик аудита получает запрос.
- ResponseStarted: После отправки заголовков ответа, но до отправки тела ответа.
- ResponseComplete: Отправка тела ответа завершена.
- Паника: события, генерируемые при возникновении паники.
Информация, захваченная для события, зависит от настроенного уровня аудита. Вы можете использовать следующие уровни аудита:
- Нет: Не регистрировать события, соответствующие этому правилу
- Метаданные: Регистрировать метаданные события запроса. Тело запроса/ответа не регистрируется.
- Запрос: Регистрировать метаданные события и тело запроса.
- RequestResponse: Регистрировать метаданные события вместе с телом запроса и ответа.
Настройка аудита Kubernetes
Настало время увидеть аудит Kubernetes в действии. В кластере с собственным хостингом аудит не включен изначально. Если вы используете управляемый кластер Kubernetes, вы можете обратиться к документации вашего поставщика, чтобы проверить, включен ли аудит по умолчанию или его нужно включить.
Кластер, используемый здесь, имеет один экземпляр control-plane и один экземпляр узла, и вы можете использовать те же шаги для кластера minikube или любого другого пустого кластера Kubernetes.
Шаг 1: Подключение к control-plane
Подключитесь к узлу control-plane и создайте каталог для размещения политики аудита, а также журналов аудита.
mkdir /etc/kubernetes/audit
Шаг 2: Создайте политику аудита
Создайте файл политики аудита с именем /etc/kubernetes/audit/policy.yaml
со следующими данными:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: None
verbs: ["get", "watch", "list"]
- level: None
resources:
- group: "" # core
resources: ["events"]
- level: None
users:
- "system:kube-scheduler"
- "system:kube-proxy"
- "system:apiserver"
- "system:kube-controller-manager"
- "system:serviceaccount:gatekeeper-system:gatekeeper-admin"
- level: None
userGroups: ["system:nodes"]
- level: RequestResponse
Шаг 3: Добавьте необходимые записи
Добавьте следующие записи в /etc/kubernetes/manifests/kube-apiserver.yaml
:
- --audit-policy-file=/etc/kubernetes/audit/policy.yaml
- --audit-log-path=/etc/kubernetes/audit/audit.log
- --audit-log-maxsize=500
- --audit-log-maxbackup=3
Прокрутите вниз и добавьте том в разделе volumes:
- hostPath:
path: /etc/kubernetes/audit
type: DirectoryOrCreate
name: audit
Теперь смонтируйте этот том, добавив следующие данные в разделе volumeMounts:
- mountPath: /etc/kubernetes/audit
name: audit
Это все, что вам нужно сделать, чтобы настроить ведение журнала аудита. Поскольку вы изменили манифест kube-apiserver, ваш kube-apiserver pod будет создан заново. Как только pod будет запущен, выполните следующую команду для создания учетной записи службы.
kubectl create sa test
Этот запрос API будет записан в файл журнала аудита (/etc/kubernetes/audit/audit.log), и вы увидите несколько подобных записей:
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"auditID": "a6029022-4ff0-4c54-97ed-4099d0ca1923",
"stage": "RequestReceived",
"requestURI": "/api/v1/namespaces/default/serviceaccounts?fieldManager=kubectl-create",
"verb": "create",
"user": {
"username": "kubernetes-admin",
"groups": ["system:masters", "system:authenticated"]
},
"sourceIPs": ["172.31.22.88"],
"userAgent": "kubectl/v1.23.6 (linux/amd64) kubernetes/ad33385",
"objectRef": {
"resource": "serviceaccounts",
"namespace": "default",
"apiVersion": "v1"
},
"requestReceivedTimestamp": "2022-07-31T08:36:48.679291Z",
"stageTimestamp": "2022-07-31T08:36:48.679291Z"
}
и
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"auditID": "a6029022-4ff0-4c54-97ed-4099d0ca1923",
"stage": "ResponseComplete",
"requestURI": "/api/v1/namespaces/default/serviceaccounts?fieldManager=kubectl-create",
"verb": "create",
"user": {
"username": "kubernetes-admin",
"groups": ["system:masters", "system:authenticated"]
},
"sourceIPs": ["172.31.22.88"],
"userAgent": "kubectl/v1.23.6 (linux/amd64) kubernetes/ad33385",
"objectRef": {
"resource": "serviceaccounts",
"namespace": "default",
"name": "test",
"apiVersion": "v1"
},
"responseStatus": {
"metadata": {},
"code": 201
},
"requestObject": {
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "test",
"creationTimestamp": null
}
},
"responseObject": {
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "test",
"namespace": "default",
"uid": "d6ea858a-206d-4b4a-aca0-499e22f00729",
"resourceVersion": "1676",
"creationTimestamp": "2022-07-31T08:36:48Z"
}
},
"requestReceivedTimestamp": "2022-07-31T08:36:48.679291Z",
"stageTimestamp": "2022-07-31T08:36:48.684377Z",
"annotations": {
"authorization.k8s.io/decision": "allow",
"authorization.k8s.io/reason": ""
}
}
Если проверить auditID, то он одинаков для обоих событий (a6029022-4ff0-4c54-97ed-4099d0ca1923), поскольку обе записи относятся к одному событию. Первая запись относится к этапу RequestReceived, а вторая — к этапу ResponseComplete. Имея эти данные, вы можете легко выяснить, что это был за запрос и кто его выполнил, посмотрев на поля sourceIPs, username, requestURI, responseStatus и responseObject.
В политике аудита, если вы измените уровень аудита с RequestResponse на MetaData, вы не увидите поля requestObject и responseObject, а если уровень аудита установлен на Request, то поле requestObject будет присутствовать, но поле responseObject не будет регистрироваться.
Возвращаясь к нашим данным о событиях, HTTP Status 201 в поле responseStatus означает, что в результате HTTP POST запроса один или несколько новых ресурсов были успешно созданы на сервере, который в данном случае является учетной записью службы. Если пользователь, не имеющий доступа к созданию учетной записи службы, попытается создать учетную запись службы, вы увидите в журнале аудита запись, подобную этой:
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"auditID": "605e41ff-394a-4b8d-bd32-86ffa984d55a",
"stage": "RequestReceived",
"requestURI": "/api/v1/namespaces/default/serviceaccounts?fieldManager=kubectl-create",
"verb": "create",
"user": {
"username": "myuser",
"groups": ["Dev", "system:authenticated"]
},
"sourceIPs": ["172.31.22.88"],
"userAgent": "kubectl/v1.23.6 (linux/amd64) kubernetes/ad33385",
"objectRef": {
"resource": "serviceaccounts",
"namespace": "default",
"apiVersion": "v1"
},
"requestReceivedTimestamp": "2022-07-31T09:00:44.262246Z",
"stageTimestamp": "2022-07-31T09:00:44.262246Z"
}
и
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "RequestResponse",
"auditID": "605e41ff-394a-4b8d-bd32-86ffa984d55a",
"stage": "ResponseComplete",
"requestURI": "/api/v1/namespaces/default/serviceaccounts?fieldManager=kubectl-create",
"verb": "create",
"user": {
"username": "myuser",
"groups": ["Dev", "system:authenticated"]
},
"sourceIPs": ["172.31.22.88"],
"userAgent": "kubectl/v1.23.6 (linux/amd64) kubernetes/ad33385",
"objectRef": {
"resource": "serviceaccounts",
"namespace": "default",
"apiVersion": "v1"
},
"responseStatus": {
"metadata": {},
"status": "Failure",
"reason": "Forbidden",
"code": 403
},
"responseObject": {
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "serviceaccounts is forbidden: User "myuser" cannot create resource "serviceaccounts" in API group "" in the namespace "default"",
"reason": "Forbidden",
"details": {
"kind": "serviceaccounts"
},
"code": 403
},
"requestReceivedTimestamp": "2022-07-31T09:00:44.262246Z",
"stageTimestamp": "2022-07-31T09:00:44.274511Z",
"annotations": {
"authorization.k8s.io/decision": "forbid",
"authorization.k8s.io/reason": ""
}
}
Это событие сообщает вам, что пользователь myuser
попытался создать учетную запись службы, но запрос был отклонен из-за недостаточного разрешения.
Поскольку эти записи имеют формат JSON, вы можете использовать инструмент jq для поиска записей журнала с помощью таких команд, как:
tail -f /etc/kubernetes/audit/audit.log | jq '.| select(.responseStatus.code | contains(403) )'
tail -f /etc/kubernetes/audit/audit.log | jq '.| select(.user.username | contains("myuser") )'
Лучшие практики для аудита Kubernetes
В производственной среде необходимо учитывать некоторые лучшие практики для аудита Kubernetes. К ним относятся:
- Создание комплексной политики аудита, основанной на ваших требованиях к ведению журналов.
- Используйте бэкенды webhook для отправки данных аудита на удаленные конечные точки вместо хранения журналов на диске
- контролировать доступ к данным аудита, чтобы их нельзя было подделать.
- Настроить оповещения и визуализацию на основе журналов аудита, чтобы вы получали информацию о важных событиях, таких как удаление секретов и т.д.
Заключительные мысли
Аудит — очень важная часть безопасности кластера Kubernetes, которая дает вам видимость событий, происходящих в вашем кластере, и помогает запустить правильно настроенный и безопасный кластер. В этой статье вы узнали о том, что такое аудит Kubernetes, почему он важен и как его настроить.
Безопасность — это бесконечный процесс, и всегда есть возможности для дальнейшей оптимизации и улучшения. Информация, представленная в этой статье, отправляет вас в путь к обеспечению безопасности вашего кластера Kubernetes, чтобы вы могли изучить его дальше.
Если вы хотите быть в курсе проблем в вашем кластере Kubernetes, вам необходимо следить за ним. SigNoz, APM с открытым исходным кодом, может отслеживать метрики, трассировки и журналы вашего кластера Kubernetes. Он создан для поддержки OpenTelemetry natively, стандарта с открытым исходным кодом для инструментария облачных приложений.
Вы можете ознакомиться с репозиторием SigNoz на GitHub здесь:
Читайте следующий блог, чтобы узнать, как мониторить кластер Kubernetes с помощью SigNoz:
Мониторинг Kubernetes с помощью инструментов с открытым исходным кодом