Kubernetes Security

Что такое kubernetes security: определение, основные принципы, примеры и практические советы. Изучайте фундаментальной защите информации с подробными объяснениями для начинающих специалистов.

Kubernetes Security - Безопасность Kubernetes

Что такое Kubernetes Security?

Kubernetes Security — это комплекс мер по обеспечению безопасности контейнерных приложений, развернутых в кластере Kubernetes. Включает защиту на уровне кластера, узлов, подов и приложений.

Основные принципы

  • Defense in Depth — многоуровневая защита
  • Least Privilege — принцип наименьших привилегий
  • Zero Trust — принцип “никому не доверяй”
  • Immutable Infrastructure — неизменяемая инфраструктура
  • Continuous Monitoring — непрерывный мониторинг

Архитектура безопасности Kubernetes

1. SecurityContext

# SecurityContext для Pod
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: nginx:1.21
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        runAsNonRoot: true
        runAsUser: 1000
        capabilities:
          drop:
            - ALL
          add:
            - NET_BIND_SERVICE
      resources:
        requests:
          memory: "64Mi"
          cpu: "250m"
        limits:
          memory: "128Mi"
          cpu: "500m"
      volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: cache
          mountPath: /var/cache
  volumes:
    - name: tmp
      emptyDir: {}
    - name: cache
      emptyDir: {}
// Система управления SecurityContext
class KubernetesSecurityContext {
  constructor() {
    this.pods = new Map();
    this.containers = new Map();
    this.securityPolicies = new Map();
  }

  // Создание безопасного Pod
  createSecurePod(podData) {
    const pod = {
      apiVersion: "v1",
      kind: "Pod",
      metadata: {
        name: podData.name,
        namespace: podData.namespace || "default",
        labels: podData.labels || {},
        annotations: podData.annotations || {},
      },
      spec: {
        securityContext: {
          runAsNonRoot: true,
          runAsUser: podData.runAsUser || 1000,
          runAsGroup: podData.runAsGroup || 1000,
          fsGroup: podData.fsGroup || 1000,
          seccompProfile: {
            type: "RuntimeDefault",
          },
        },
        containers: podData.containers.map((container) => ({
          name: container.name,
          image: container.image,
          securityContext: {
            allowPrivilegeEscalation: false,
            readOnlyRootFilesystem: true,
            runAsNonRoot: true,
            runAsUser: container.runAsUser || 1000,
            capabilities: {
              drop: ["ALL"],
              add: container.capabilities || [],
            },
          },
          resources: {
            requests: container.resources?.requests || {
              memory: "64Mi",
              cpu: "250m",
            },
            limits: container.resources?.limits || {
              memory: "128Mi",
              cpu: "500m",
            },
          },
          volumeMounts: container.volumeMounts || [],
        })),
        volumes: podData.volumes || [],
      },
    };

    this.pods.set(podData.name, pod);

    return {
      success: true,
      pod: pod,
    };
  }

  // Создание SecurityPolicy
  createSecurityPolicy(policyData) {
    const policy = {
      apiVersion: "policy/v1beta1",
      kind: "PodSecurityPolicy",
      metadata: {
        name: policyData.name,
        namespace: policyData.namespace || "default",
      },
      spec: {
        privileged: false,
        allowPrivilegeEscalation: false,
        requiredDropCapabilities: ["ALL"],
        volumes: policyData.allowedVolumes || [
          "configMap",
          "emptyDir",
          "projected",
          "secret",
          "downwardAPI",
          "persistentVolumeClaim",
        ],
        runAsUser: {
          rule: "MustRunAsNonRoot",
        },
        seLinux: {
          rule: "RunAsAny",
        },
        fsGroup: {
          rule: "RunAsAny",
        },
        readOnlyRootFilesystem: policyData.readOnlyRootFilesystem || false,
      },
    };

    this.securityPolicies.set(policyData.name, policy);

    return {
      success: true,
      policy: policy,
    };
  }

  // Валидация SecurityContext
  validateSecurityContext(pod) {
    const issues = [];

    // Проверка runAsNonRoot
    if (!pod.spec.securityContext?.runAsNonRoot) {
      issues.push("Pod should run as non-root user");
    }

    // Проверка allowPrivilegeEscalation
    for (const container of pod.spec.containers) {
      if (container.securityContext?.allowPrivilegeEscalation) {
        issues.push(`Container ${container.name} allows privilege escalation`);
      }
    }

    // Проверка readOnlyRootFilesystem
    for (const container of pod.spec.containers) {
      if (!container.securityContext?.readOnlyRootFilesystem) {
        issues.push(
          `Container ${container.name} should use read-only root filesystem`
        );
      }
    }

    // Проверка capabilities
    for (const container of pod.spec.containers) {
      const capabilities = container.securityContext?.capabilities;
      if (capabilities && capabilities.add && capabilities.add.length > 0) {
        const dangerousCaps = ["SYS_ADMIN", "SYS_PTRACE", "SYS_MODULE"];
        const hasDangerousCaps = capabilities.add.some((cap) =>
          dangerousCaps.includes(cap)
        );
        if (hasDangerousCaps) {
          issues.push(`Container ${container.name} has dangerous capabilities`);
        }
      }
    }

    return {
      valid: issues.length === 0,
      issues: issues,
    };
  }
}

2. Network Policies

# NetworkPolicy для ограничения трафика
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-app-netpol
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: web-app
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: frontend
        - podSelector:
            matchLabels:
              app: load-balancer
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: database
      ports:
        - protocol: TCP
          port: 5432
    - to: []
      ports:
        - protocol: TCP
          port: 53
        - protocol: UDP
          port: 53
// Система управления Network Policies
class KubernetesNetworkPolicies {
  constructor() {
    this.networkPolicies = new Map();
    this.namespaces = new Map();
    this.pods = new Map();
  }

  // Создание NetworkPolicy
  createNetworkPolicy(policyData) {
    const policy = {
      apiVersion: "networking.k8s.io/v1",
      kind: "NetworkPolicy",
      metadata: {
        name: policyData.name,
        namespace: policyData.namespace || "default",
      },
      spec: {
        podSelector: policyData.podSelector || {},
        policyTypes: policyData.policyTypes || ["Ingress", "Egress"],
        ingress: policyData.ingress || [],
        egress: policyData.egress || [],
      },
    };

    this.networkPolicies.set(policyData.name, policy);

    return {
      success: true,
      policy: policy,
    };
  }

  // Создание правила Ingress
  createIngressRule(ruleData) {
    const rule = {
      from: ruleData.from || [],
      ports: ruleData.ports || [],
    };

    return rule;
  }

  // Создание правила Egress
  createEgressRule(ruleData) {
    const rule = {
      to: ruleData.to || [],
      ports: ruleData.ports || [],
    };

    return rule;
  }

  // Создание селектора namespace
  createNamespaceSelector(namespaceData) {
    return {
      namespaceSelector: {
        matchLabels: namespaceData.matchLabels || {},
      },
    };
  }

  // Создание селектора pod
  createPodSelector(podData) {
    return {
      podSelector: {
        matchLabels: podData.matchLabels || {},
      },
    };
  }

  // Создание правила порта
  createPortRule(portData) {
    return {
      protocol: portData.protocol || "TCP",
      port: portData.port,
    };
  }

  // Валидация NetworkPolicy
  validateNetworkPolicy(policy) {
    const issues = [];

    // Проверка наличия podSelector
    if (!policy.spec.podSelector) {
      issues.push("NetworkPolicy must have podSelector");
    }

    // Проверка policyTypes
    if (!policy.spec.policyTypes || policy.spec.policyTypes.length === 0) {
      issues.push("NetworkPolicy must specify policyTypes");
    }

    // Проверка правил Ingress
    if (policy.spec.policyTypes.includes("Ingress")) {
      if (!policy.spec.ingress || policy.spec.ingress.length === 0) {
        issues.push(
          "NetworkPolicy with Ingress policyType must have ingress rules"
        );
      }
    }

    // Проверка правил Egress
    if (policy.spec.policyTypes.includes("Egress")) {
      if (!policy.spec.egress || policy.spec.egress.length === 0) {
        issues.push(
          "NetworkPolicy with Egress policyType must have egress rules"
        );
      }
    }

    return {
      valid: issues.length === 0,
      issues: issues,
    };
  }
}

3. RBAC (Role-Based Access Control)

# Role для доступа к Pods
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
  - apiGroups: ["]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
  - apiGroups: ["]
    resources: ["pods/log"]
    verbs: ["get", "list"]

---
# ClusterRole для администратора
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-admin
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
  - nonResourceURLs: ["*"]
    verbs: ["*"]

---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: production
subjects:
  - kind: User
    name: developer
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
// Система управления RBAC
class KubernetesRBAC {
  constructor() {
    this.roles = new Map();
    this.clusterRoles = new Map();
    this.roleBindings = new Map();
    this.clusterRoleBindings = new Map();
    this.users = new Map();
    this.groups = new Map();
  }

  // Создание Role
  createRole(roleData) {
    const role = {
      apiVersion: "rbac.authorization.k8s.io/v1",
      kind: "Role",
      metadata: {
        name: roleData.name,
        namespace: roleData.namespace || "default",
      },
      rules: roleData.rules || [],
    };

    this.roles.set(roleData.name, role);

    return {
      success: true,
      role: role,
    };
  }

  // Создание ClusterRole
  createClusterRole(roleData) {
    const clusterRole = {
      apiVersion: "rbac.authorization.k8s.io/v1",
      kind: "ClusterRole",
      metadata: {
        name: roleData.name,
      },
      rules: roleData.rules || [],
    };

    this.clusterRoles.set(roleData.name, clusterRole);

    return {
      success: true,
      clusterRole: clusterRole,
    };
  }

  // Создание правила RBAC
  createRBACRule(ruleData) {
    const rule = {
      apiGroups: ruleData.apiGroups || [],
      resources: ruleData.resources || [],
      verbs: ruleData.verbs || [],
      nonResourceURLs: ruleData.nonResourceURLs || [],
    };

    return rule;
  }

  // Создание RoleBinding
  createRoleBinding(bindingData) {
    const binding = {
      apiVersion: "rbac.authorization.k8s.io/v1",
      kind: "RoleBinding",
      metadata: {
        name: bindingData.name,
        namespace: bindingData.namespace || "default",
      },
      subjects: bindingData.subjects || [],
      roleRef: bindingData.roleRef || {},
    };

    this.roleBindings.set(bindingData.name, binding);

    return {
      success: true,
      binding: binding,
    };
  }

  // Создание ClusterRoleBinding
  createClusterRoleBinding(bindingData) {
    const binding = {
      apiVersion: "rbac.authorization.k8s.io/v1",
      kind: "ClusterRoleBinding",
      metadata: {
        name: bindingData.name,
      },
      subjects: bindingData.subjects || [],
      roleRef: bindingData.roleRef || {},
    };

    this.clusterRoleBindings.set(bindingData.name, binding);

    return {
      success: true,
      binding: binding,
    };
  }

  // Создание субъекта
  createSubject(subjectData) {
    const subject = {
      kind: subjectData.kind, // User, Group, ServiceAccount
      name: subjectData.name,
      namespace: subjectData.namespace,
      apiGroup: subjectData.apiGroup || "rbac.authorization.k8s.io",
    };

    return subject;
  }

  // Создание ссылки на роль
  createRoleRef(roleRefData) {
    const roleRef = {
      kind: roleRefData.kind, // Role, ClusterRole
      name: roleRefData.name,
      apiGroup: roleRefData.apiGroup || "rbac.authorization.k8s.io",
    };

    return roleRef;
  }

  // Проверка доступа
  checkAccess(user, resource, verb, namespace) {
    // Получение всех ролей пользователя
    const userRoles = this.getUserRoles(user, namespace);

    // Проверка доступа для каждой роли
    for (const role of userRoles) {
      if (this.roleHasAccess(role, resource, verb)) {
        return true;
      }
    }

    return false;
  }

  // Получение ролей пользователя
  getUserRoles(user, namespace) {
    const roles = [];

    // Поиск в RoleBindings
    for (const [name, binding] of this.roleBindings) {
      if (binding.metadata.namespace === namespace) {
        for (const subject of binding.subjects) {
          if (subject.kind === "User" && subject.name === user) {
            const role = this.roles.get(binding.roleRef.name);
            if (role) {
              roles.push(role);
            }
          }
        }
      }
    }

    // Поиск в ClusterRoleBindings
    for (const [name, binding] of this.clusterRoleBindings) {
      for (const subject of binding.subjects) {
        if (subject.kind === "User" && subject.name === user) {
          const clusterRole = this.clusterRoles.get(binding.roleRef.name);
          if (clusterRole) {
            roles.push(clusterRole);
          }
        }
      }
    }

    return roles;
  }

  // Проверка доступа роли
  roleHasAccess(role, resource, verb) {
    for (const rule of role.rules) {
      if (this.ruleMatches(rule, resource, verb)) {
        return true;
      }
    }

    return false;
  }

  // Проверка соответствия правила
  ruleMatches(rule, resource, verb) {
    // Проверка ресурсов
    if (rule.resources && rule.resources.length > 0) {
      if (!rule.resources.includes(resource) && !rule.resources.includes("*")) {
        return false;
      }
    }

    // Проверка глаголов
    if (rule.verbs && rule.verbs.length > 0) {
      if (!rule.verbs.includes(verb) && !rule.verbs.includes("*")) {
        return false;
      }
    }

    return true;
  }
}

4. Pod Security Standards

# Pod Security Policy для production
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: production-psp
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - "configMap"
    - "emptyDir"
    - "projected"
    - "secret"
    - "downwardAPI"
    - "persistentVolumeClaim"
  runAsUser:
    rule: "MustRunAsNonRoot"
  seLinux:
    rule: "RunAsAny"
  fsGroup:
    rule: "RunAsAny"
  readOnlyRootFilesystem: true
// Система управления Pod Security
class KubernetesPodSecurity {
  constructor() {
    this.securityPolicies = new Map();
    this.securityStandards = new Map();
    this.admissionControllers = new Map();
  }

  // Создание Pod Security Policy
  createPodSecurityPolicy(policyData) {
    const policy = {
      apiVersion: "policy/v1beta1",
      kind: "PodSecurityPolicy",
      metadata: {
        name: policyData.name,
      },
      spec: {
        privileged: policyData.privileged || false,
        allowPrivilegeEscalation: policyData.allowPrivilegeEscalation || false,
        requiredDropCapabilities: policyData.requiredDropCapabilities || [
          "ALL",
        ],
        volumes: policyData.allowedVolumes || [
          "configMap",
          "emptyDir",
          "projected",
          "secret",
          "downwardAPI",
          "persistentVolumeClaim",
        ],
        runAsUser: policyData.runAsUser || {
          rule: "MustRunAsNonRoot",
        },
        seLinux: policyData.seLinux || {
          rule: "RunAsAny",
        },
        fsGroup: policyData.fsGroup || {
          rule: "RunAsAny",
        },
        readOnlyRootFilesystem: policyData.readOnlyRootFilesystem || true,
      },
    };

    this.securityPolicies.set(policyData.name, policy);

    return {
      success: true,
      policy: policy,
    };
  }

  // Создание Security Standard
  createSecurityStandard(standardData) {
    const standard = {
      name: standardData.name,
      level: standardData.level, // privileged, baseline, restricted
      rules: standardData.rules || [],
      description: standardData.description || ",
    };

    this.securityStandards.set(standardData.name, standard);

    return {
      success: true,
      standard: standard,
    };
  }

  // Создание Admission Controller
  createAdmissionController(controllerData) {
    const controller = {
      name: controllerData.name,
      type: controllerData.type, // validating, mutating
      rules: controllerData.rules || [],
      configuration: controllerData.configuration || {},
      enabled: controllerData.enabled !== false,
    };

    this.admissionControllers.set(controllerData.name, controller);

    return {
      success: true,
      controller: controller,
    };
  }

  // Валидация Pod против Security Standard
  validatePodAgainstStandard(pod, standardName) {
    const standard = this.securityStandards.get(standardName);
    if (!standard) {
      return { valid: false, error: "Standard not found" };
    }

    const issues = [];

    // Проверка уровня стандарта
    switch (standard.level) {
      case "privileged":
        // Минимальные ограничения
        break;
      case "baseline":
        issues.push(...this.validateBaselineStandard(pod));
        break;
      case "restricted":
        issues.push(...this.validateRestrictedStandard(pod));
        break;
    }

    return {
      valid: issues.length === 0,
      issues: issues,
    };
  }

  // Валидация Baseline Standard
  validateBaselineStandard(pod) {
    const issues = [];

    // Проверка privileged
    if (pod.spec.securityContext?.privileged) {
      issues.push("Privileged containers are not allowed");
    }

    // Проверка host namespaces
    if (pod.spec.hostNetwork || pod.spec.hostPID || pod.spec.hostIPC) {
      issues.push("Host namespaces are not allowed");
    }

    // Проверка host ports
    for (const container of pod.spec.containers) {
      if (container.ports) {
        for (const port of container.ports) {
          if (port.hostPort) {
            issues.push("Host ports are not allowed");
          }
        }
      }
    }

    return issues;
  }

  // Валидация Restricted Standard
  validateRestrictedStandard(pod) {
    const issues = [];

    // Все проверки Baseline
    issues.push(...this.validateBaselineStandard(pod));

    // Проверка runAsNonRoot
    if (!pod.spec.securityContext?.runAsNonRoot) {
      issues.push("Must run as non-root user");
    }

    // Проверка readOnlyRootFilesystem
    for (const container of pod.spec.containers) {
      if (!container.securityContext?.readOnlyRootFilesystem) {
        issues.push("Must use read-only root filesystem");
      }
    }

    // Проверка capabilities
    for (const container of pod.spec.containers) {
      const capabilities = container.securityContext?.capabilities;
      if (capabilities && capabilities.add && capabilities.add.length > 0) {
        issues.push("Additional capabilities are not allowed");
      }
    }

    return issues;
  }
}

Основные компоненты безопасности

1. Cluster Security

  • API Server Security — безопасность API сервера
  • etcd Security — безопасность etcd
  • Node Security — безопасность узлов
  • Network Security — сетевая безопасность

2. Container Security

  • Image Security — безопасность образов
  • Runtime Security — безопасность рантайма
  • Registry Security — безопасность реестра
  • Scanning — сканирование уязвимостей

3. Application Security

  • Secrets Management — управление секретами
  • ConfigMaps — конфигурационные карты
  • Service Accounts — сервисные аккаунты
  • Network Policies — сетевые политики

Best Practices

1. Pod Security

  • Non-root containers — контейнеры без root
  • Read-only filesystem — только для чтения
  • Resource limits — ограничения ресурсов
  • Security contexts — контексты безопасности

2. Network Security

  • Network policies — сетевые политики
  • Service mesh — сервисная сетка
  • TLS everywhere — TLS везде
  • Firewall rules — правила брандмауэра

3. Access Control

  • RBAC — контроль доступа на основе ролей
  • Least privilege — принцип наименьших привилегий
  • Regular audits — регулярные аудиты
  • Service accounts — сервисные аккаунты

4. Monitoring

  • Log aggregation — агрегация логов
  • Metrics collection — сбор метрик
  • Alerting — уведомления
  • Incident response — реагирование на инциденты

Заключение

Kubernetes Security — это комплексный подход к обеспечению безопасности контейнерных приложений, который требует:

  • Правильной конфигурации — настройки всех компонентов
  • Строгого контроля доступа — ограничения доступа
  • Непрерывного мониторинга — отслеживания состояния
  • Регулярного обновления — обновления компонентов

Помните: безопасность Kubernetes — это не разовое мероприятие, а постоянный процесс. Регулярно обновляйте политики, следите за новыми угрозами и адаптируйте меры защиты.


Совет: Начните с настройки RBAC и Network Policies, затем внедрите SecurityContext и Pod Security Standards. Не забывайте о регулярном сканировании образов и мониторинге кластера!