Grupos de seguridad de Pods - Amazon EKS

Grupos de seguridad de Pods

Los grupos de seguridad de Pods integran los grupos de seguridad de Amazon EC2 con los Pods de Kubernetes. Puede utilizar grupos de seguridad de Amazon EC2 para definir reglas que permitan el tráfico de red entrante y saliente hacia y desde los Pods que implemente en nodos que se ejecutan en muchos tipos de instancias de Amazon EC2 y Fargate. Para obtener una explicación más detallada de esta capacidad, consulte la publicación de blog Presentación de los grupos de seguridad para Pods.

Consideraciones

  • Antes de implementar grupos de seguridad para Pods, tenga en cuenta las siguientes limitaciones y condiciones:

  • Los grupos de seguridad de Pods no se pueden utilizar con nodos de Windows.

  • Los grupos de seguridad para Pods pueden utilizarse en clústeres configurados para la familia IPv6 que contengan nodos de Amazon EC2 mediante la versión 1.16.0 o posterior del complemento CNI de Amazon VPC. Puede usar grupos de seguridad para Pods con clústeres configurados para la familia IPv6 que contengan solo nodos de Fargate mediante la versión 1.7.7 o posterior del complemento CNI de Amazon VPC. Para obtener más información, consulte Direcciones IPv6 de clústeres, Pods y services

  • Los grupos de seguridad para Pods son compatibles con la mayoría de las familias de instancias de Amazon EC2 basadas en Nitro, aunque no en todas las generaciones de una familia. Por ejemplo, las generaciones y familia de instancias m5, c5, r5, p3, m6g, c6g y r6g son compatibles. No se admite ningún tipo de instancia de la familia t. Para obtener una lista completa de los tipos de instancias compatibles, consulte el archivo limits.go en GitHub. Sus nodos deben ser uno de los tipos de instancias enumerados que tienen IsTrunkingCompatible: true en ese archivo.

  • Si también utiliza políticas de seguridad del Pod a fin de restringir el acceso a la mutación de Pod, el usuario del eks:vpc-resource-controller de Kubernetes debe especificarse en ClusterRoleBinding de Kubernetes para el role al que se le asigna psp. Si utiliza el psp, role y ClusterRoleBinding predeterminados de Amazon EKS, este es el ClusterRoleBinding de eks:podsecuritypolicy:authenticated. Por ejemplo, agrega el usuario a la sección subjects:, tal como se muestra en el siguiente ejemplo:

    [...] subjects: - kind: Group apiGroup: rbac.authorization.k8s.io name: system:authenticated - apiGroup: rbac.authorization.k8s.io kind: User name: eks:vpc-resource-controller - kind: ServiceAccount name: eks-vpc-resource-controller
  • Si utiliza redes y grupos de seguridad personalizados para los Pods de forma conjunta, se utiliza el grupo de seguridad especificado por los grupos de seguridad de Pods en lugar del grupo de seguridad especificado en ENIConfig.

  • Si utiliza la versión 1.10.2 o anterior del complemento CNI de Amazon VPC e incluye la configuración de terminationGracePeriodSeconds en la especificación del Pod, el valor de la configuración no puede ser cero.

  • Si utiliza la versión 1.10 o anterior del complemento CNI de Amazon VPC o la versión 1.11 con POD_SECURITY_GROUP_ENFORCING_MODE=strict, que es la configuración predeterminada, entonces los servicios de Kubernetes de tipo NodePort y LoadBalancer con destinos de instancia con un conjunto externalTrafficPolicy establecido en Local no son compatibles con los Pods a los que asigna grupos de seguridad. Para obtener más información sobre el uso de un equilibrador de carga con destinos de instancia, consulte Equilibrio de carga de red en Amazon EKS

  • Si utiliza la versión 1.10 o anterior del complemento o versión CNI de Amazon VPC 1.11 con POD_SECURITY_GROUP_ENFORCING_MODE=strict, que es la configuración predeterminada, el NAT de origen está deshabilitado para el tráfico saliente de Pods con grupos de seguridad asignados a fin de que se apliquen las reglas de grupo de seguridad salientes. Para acceder a Internet, los Pods con grupos de seguridad asignados deben lanzarse en nodos que se implementen en una subred privada configurada con una instancia o puerta de enlace NAT. Los Pods con los grupos de seguridad asignados implementados en subredes públicas no pueden acceder a la internet.

    Si utiliza la versión 1.11 o posterior del plugin con POD_SECURITY_GROUP_ENFORCING_MODE=standard, entonces el tráfico de Pod destinado para salir de la VPC se traduce a la dirección IP de la interfaz de red principal de la instancia. Para este tráfico, se utilizan las reglas de los grupos de seguridad de la interfaz de red principal, en lugar de las reglas de los grupos de seguridad de los Pod's.

  • Para utilizar la política de red de Calico con Pods que tienen grupos de seguridad asociados, debe utilizar la versión 1.11.0 o posterior del complemento CNI de Amazon VPC y establecerla en POD_SECURITY_GROUP_ENFORCING_MODE=standard. De otro modo, el flujo de tráfico hacia y desde los Pods con grupos de seguridad asociados no están sujetos al cumplimiento de la política de red de Calico y solo se limitan a la aplicación de grupos de seguridad de Amazon EC2. Para actualizar la versión del CNI de Amazon VPC, consulte Trabajar con el complemento Amazon VPC CNI plugin for Kubernetes de Amazon EKS

  • Los Pods que funciona en nodos de Amazon EC2 que utilizan grupos de seguridad en clústeres que utilizan Nodelocal DNSCache solo se admiten con la versión 1.11.0 o posterior del complemento CNI de Amazon VPC y con POD_SECURITY_GROUP_ENFORCING_MODE=standard. Para actualizar la versión del complemento CNI de Amazon VPC, consulte Trabajar con el complemento Amazon VPC CNI plugin for Kubernetes de Amazon EKS

  • Los grupos de seguridad de Pods pueden generar un aumento en la latencia de inicio de un Pod en el caso de los Pods con alta pérdida. Esto se debe a la limitación de velocidad en el controlador de recursos.

Configuración del Amazon VPC CNI plugin for Kubernetes para grupos de seguridad de los Pods

Para implementar grupos de seguridad de Pods

Si solo utiliza grupos de seguridad para Pods de Fargate y no cuenta con nodos de Amazon EC2 en el clúster, vaya al paso Implemente un aplicación de ejemplo .

  1. Verifique su versión del Amazon VPC CNI plugin for Kubernetes actual con el siguiente comando:

    kubectl describe daemonset aws-node --namespace kube-system | grep amazon-k8s-cni: | cut -d : -f 3

    Un ejemplo de salida sería el siguiente.

    v1.7.6

    Si su versión del Amazon VPC CNI plugin for Kubernetes es anterior a la 1.7.7, actualice el complemento a la versión 1.7.7 o posterior. Para obtener más información, consulte Trabajar con el complemento Amazon VPC CNI plugin for Kubernetes de Amazon EKS

  2. Agregue la política de IAM administrada AmazonEKSVPCResourceController al rol de clúster asociado a su clúster de Amazon EKS. La política permite que el rol administre las interfaces de red, sus direcciones IP privadas y su vinculación y desvinculación desde y hacia las instancias de red.

    1. Recupere el nombre del rol de IAM de su clúster y guárdelo en una variable. Reemplace my-cluster por el nombre del clúster.

      cluster_role=$(aws eks describe-cluster --name my-cluster --query cluster.roleArn --output text | cut -d / -f 2)
    2. Asocie la política al rol.

      aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKSVPCResourceController --role-name $cluster_role
  3. Habilite el complemento CNI de Amazon VPC para administrar las interfaces de red de los Pods al establecer la variable ENABLE_POD_ENI en true en el aws-node DaemonSet. Una vez que esta configuración se establece en true, para cada nodo del clúster, el complemento crea un recurso personalizado de cninode. El controlador de recursos de VPC crea y adjunta una interfaz de red especial denominada interfaz de red troncal con la descripción aws-k8s-trunk-eni.

    kubectl set env daemonset aws-node -n kube-system ENABLE_POD_ENI=true
    nota

    La interfaz de red troncal se incluye en el número máximo de interfaces de red que admite el tipo de instancia. A fin de obtener una lista del número máximo de interfaces de red que admite cada tipo de instancia, consulte Direcciones IP por interfaz de red por tipo de instancia en la Guía del usuario de Amazon EC2 para instancias de Linux. Si su nodo ya cuenta con el número máximo de interfaces de red estándar adjuntas, el controlador de recursos de VPC reservará un espacio. Tendrá que reducir verticalmente los Pods en ejecución lo suficiente para que el controlador desconecte y elimine una interfaz de red estándar, cree la interfaz de red troncal y la adjunte a la instancia.

  4. Si desea ver cuál de sus nodos tiene un recurso personalizado CNINode establecido, utilice el siguiente comando. Si se devuelve No resources found, espere varios segundos e inténtelo de nuevo. El paso anterior requiere reiniciar los Pods del Amazon VPC CNI plugin for Kubernetes, lo cual tarda varios segundos.

    $ kubectl get cninode -A NAME FEATURES ip-192-168-64-141.us-west-2.compute.internal [{"name":"SecurityGroupsForPods"}] ip-192-168-7-203.us-west-2.compute.internal [{"name":"SecurityGroupsForPods"}]

    Si utiliza versiones de CNI de VPC anteriores a 1.15, se utilizaron etiquetas de nodo en lugar del recurso personalizado CNINode. Si desea ver cuál de sus nodos tienen la etiqueta de nodo aws-k8s-trunk-eni establecida en true, utilice el siguiente comando. Si se devuelve No resources found, espere varios segundos e inténtelo de nuevo. El paso anterior requiere reiniciar los Pods del Amazon VPC CNI plugin for Kubernetes, lo cual tarda varios segundos.

    kubectl get nodes -o wide -l vpc.amazonaws.com/has-trunk-attached=true -

    Una vez que se crea la interfaz de red troncal, se pueden asignar direcciones IP secundarias a los Pods desde las interfaces de red troncales o estándar. La interfaz troncal se elimina de forma automática si se elimina el nodo.

    Cuando implementa un grupo de seguridad para un Pod en un paso posterior, el controlador de recursos de VPC crea una interfaz de red especial denominada interfaz de red de ramificación con una descripción de aws-k8s-branch-eni y les asocia los grupos de seguridad. Se crean las interfaces de red de ramificación además de las interfaces de red estándar y troncal adjuntas al nodo.

    Si utiliza sondeos de estado o preparación, también necesita desactivar el demux temprano de TCP, de modo que kubelet pueda conectarse a los Pods en las interfaces de red de ramificación a través de TCP. Para desactivar el demux temprano de TCP, ejecute el siguiente comando:

    kubectl patch daemonset aws-node -n kube-system \ -p '{"spec": {"template": {"spec": {"initContainers": [{"env":[{"name":"DISABLE_TCP_EARLY_DEMUX","value":"true"}],"name":"aws-vpc-cni-init"}]}}}}'
    nota

    Si utiliza 1.11.0 o posterior del complemento Amazon VPC CNI plugin for Kubernetes y lo establece en POD_SECURITY_GROUP_ENFORCING_MODE=standard, como se describe en el siguiente paso, no es necesario ejecutar el comando anterior.

  5. Si su clúster usa NodeLocal DNSCache o desea usar la política de red de Calico con los Pods que tienen sus propios grupos de seguridad, o si tiene servicios de Kubernetes de tipo NodePort y LoadBalancer mediante los destinos de instancia con una externalTrafficPolicy establecida en Local para Pods a los que desea asignar grupos de seguridad, debe usar la versión 1.11.0 o posterior del complemento Amazon VPC CNI plugin for Kubernetes y habilitar la siguiente configuración:

    kubectl set env daemonset aws-node -n kube-system POD_SECURITY_GROUP_ENFORCING_MODE=standard
    importante
    • Las reglas del grupo de seguridad del Pod no se aplican al tráfico entre Pods o entre Pods y services, como kubelet o nodeLocalDNS, que se encuentran en el mismo nodo. Los pods que utilizan diferentes grupos de seguridad en el mismo nodo no pueden comunicarse porque están configurados en diferentes subredes y el enrutamiento está deshabilitado entre estas subredes.

    • Tráfico saliente de Pods a las direcciones fuera de la VPC es la dirección de red traducida a la dirección IP de la interfaz de red principal de la instancia (a menos que también haya configurado AWS_VPC_K8S_CNI_EXTERNALSNAT=true). Para este tráfico, se utilizan las reglas de los grupos de seguridad de la interfaz de red principal, en lugar de las reglas de los grupos de seguridad de los Pod's.

    • Para que esta configuración se aplique a los Pods existentes, debe reiniciar los Pods o los nodos en que se están ejecutando los Pods.

Implemente un aplicación de ejemplo

Para utilizar grupos de seguridad para Pods, debe tener un grupo de seguridad existente e Implementar un Amazon EKS SecurityGroupPolicy al clúster, tal y como se describe en el siguiente procedimiento. En los siguientes pasos se muestra cómo utilizar la política de grupo de seguridad para un Pod. A menos que se indique lo contrario, complete todos los pasos del mismo terminal ya que en los siguientes pasos se utilizan variables que no persisten en los terminales.

Para implementar un ejemplo de Pod con un grupo de seguridad
  1. Cree un espacio de nombres de Kubernetes en el que implementar los recursos. Puede reemplazar my-namespace por el nombre del espacio de nombres que desee usar.

    kubectl create namespace my-namespace
  2. Implemente una SecurityGroupPolicy de Amazon EKS en su clúster.

    1. Copie los siguientes contenidos en su dispositivo. Puede reemplazar podSelector por serviceAccountSelector si prefiere seleccionar Pods en función de las etiquetas de cuenta de servicio. Debe especificar un selector o el otro. Un podSelector vacío (ejemplo: podSelector: {}) selecciona todos los Pods del espacio de nombres. Puede cambiar my-role por el nombre de su rol. Un serviceAccountSelector vacío selecciona todas las cuentas de servicio del espacio de nombres. Puede reemplazar my-security-group-policy por un nombre para su SecurityGroupPolicy y my-namespace por el espacio de nombres en el que desea crear la SecurityGroupPolicy.

      Debe reemplazar my_pod_security_group_id por el ID de un grupo de seguridad existente. Si no dispone de un grupo de seguridad existente, debe crear uno. Para obtener más información, consulte Grupos de seguridad de Amazon EC2 para instancias de Linux en la Guía del usuario de instancias de Linux de Amazon EC2. Puede especificar de uno a cinco ID de grupo de seguridad. Si especifica más de un ID, la combinación de todas las reglas de todos los grupos de seguridad será efectiva para los Pods seleccionados.

      cat >my-security-group-policy.yaml <<EOF apiVersion: vpcresources.k8s.aws/v1beta1 kind: SecurityGroupPolicy metadata: name: my-security-group-policy namespace: my-namespace spec: podSelector: matchLabels: role: my-role securityGroups: groupIds: - my_pod_security_group_id EOF
      importante

      El grupo o grupos de seguridad que especifique para sus Pod debe cumplir los siguientes criterios:

      • Deben existir. Si no existen, entonces, cuando implementa un Pod que coincida con el selector, el Pod permanece atascado en el proceso de creación. Si describe el Pod, verá un mensaje de error similar al siguiente: An error occurred (InvalidSecurityGroupID.NotFound) when calling the CreateNetworkInterface operation: The securityGroup ID 'sg-05b1d815d1EXAMPLE' does not exist.

      • Deben permitir la comunicación entrante desde el grupo de seguridad de clúster aplicado a sus nodos (para kubelet) a través de los puertos para los que haya configurado sondeos.

      • Deben permitir la comunicación saliente a través de los puertos TCP y UDP 53 a un grupo de seguridad asignado a los Pods (o los nodos en los que los Pods se ejecutan) que ejecutan CoreDNS. El grupo de seguridad de sus Pods de CoreDNS debe permitir el tráfico entrante del puerto TCP y UDP 53 del grupo de seguridad que especifique.

      • Deben tener las reglas entrantes y salientes necesarias para comunicarse con otros Pods con los que deben comunicarse.

      • Deben tener reglas que permitan a los Pods comunicarse con el plano de control de Kubernetes si utilizan el grupo de seguridad con Fargate. La forma más sencilla de hacerlo es especificar el grupo de seguridad de clúster como uno de los grupos de seguridad.

      Las políticas de grupos de seguridad solo se aplican a los nuevos Pods programados. No afectan a los Pods en ejecución.

    2. Implemente la política.

      kubectl apply -f my-security-group-policy.yaml
  3. Implemente una aplicación de muestra con una etiqueta que coincida con el valor my-role para podSelector que especificó en un paso anterior.

    1. Copie los siguientes contenidos en su dispositivo. Reemplace los valores de ejemplo por los suyos y, a continuación, ejecute el comando modificado. Si reemplaza my-role, asegúrese de que sea igual al valor que especificó para el selector en un paso anterior.

      cat >sample-application.yaml <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment namespace: my-namespace labels: app: my-app spec: replicas: 4 selector: matchLabels: app: my-app template: metadata: labels: app: my-app role: my-role spec: terminationGracePeriodSeconds: 120 containers: - name: nginx image: public.ecr.aws/nginx/nginx:1.23 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-app namespace: my-namespace labels: app: my-app spec: selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 80 EOF
    2. Implemente la aplicación con el siguiente comando. Cuando implementa la aplicación, el Amazon VPC CNI plugin for Kubernetes coincide con la etiqueta de role y los grupos de seguridad que especificó en el paso anterior se aplican al Pod.

      kubectl apply -f sample-application.yaml
  4. Vea los Pods implementados con la aplicación de muestra. En el resto de este tema, se hace referencia a este terminal como TerminalA.

    kubectl get pods -n my-namespace -o wide

    Un ejemplo de salida sería el siguiente.

    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-deployment-5df6f7687b-4fbjm 1/1 Running 0 7m51s 192.168.53.48 ip-192-168-33-28.region-code.compute.internal <none> <none> my-deployment-5df6f7687b-j9fl4 1/1 Running 0 7m51s 192.168.70.145 ip-192-168-92-33.region-code.compute.internal <none> <none> my-deployment-5df6f7687b-rjxcz 1/1 Running 0 7m51s 192.168.73.207 ip-192-168-92-33.region-code.compute.internal <none> <none> my-deployment-5df6f7687b-zmb42 1/1 Running 0 7m51s 192.168.63.27 ip-192-168-33-28.region-code.compute.internal <none> <none>
    nota
    • Si hay Pods atascados en estado Waiting, ejecute kubectl describe pod my-deployment-xxxxxxxxxx-xxxxx -n my-namespace. Si ve Insufficient permissions: Unable to create Elastic Network Interface., confirme que agregó la política de IAM al rol de clúster de IAM en un paso anterior.

    • Si algún Pods se encuentra atascado en estado Pending, confirme que el tipo de instancia del nodo aparece en limits.go y que el producto del número máximo de interfaces de red de ramificación admitidas por el tipo de instancia multiplicado por el número de nodos del grupo de nodos aún no se ha alcanzado. Por ejemplo, una instancia m5.large admite nueve interfaces de red de ramificación. Si el grupo de nodos tiene cinco nodos, se puede crear un máximo de 45 interfaces de red de ramificación para el grupo de nodos. El Pod 46 que intente implementar se establecerá en el estado Pending hasta que se elimine otro Pod que tenga grupos de seguridad asociados.

    Si ejecuta kubectl describe pod my-deployment-xxxxxxxxxx-xxxxx -n my-namespace y ve un mensaje similar al siguiente mensaje, puede ignorarlo de forma segura. Este mensaje puede aparecer cuando el Amazon VPC CNI plugin for Kubernetes intenta configurar las redes de host y falla mientras se crea la interfaz de red. El complemento registra este evento hasta que se crea la interfaz de red.

    Failed to create Pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "e24268322e55c8185721f52df6493684f6c2c3bf4fd59c9c121fd4cdc894579f" network for Pod "my-deployment-5df6f7687b-4fbjm": networkPlugin
    cni failed to set up Pod "my-deployment-5df6f7687b-4fbjm-c89wx_my-namespace" network: add cmd: failed to assign an IP address to container

    No puede exceder el número máximo de Pods que se pueden ejecutar en el tipo de instancia. Para obtener una lista del número máximo de Pods que puede ejecutar en cada tipo de instancia, consulte eni-max-pods.txt en GitHub. Cuando elimina un Pod que tiene grupos de seguridad asociados o elimina el nodo en el que se ejecuta el Pod, el controlador de recursos de VPC elimina la interfaz de red de ramificación. Si elimina un clúster con Pods mediante Pods para grupos de seguridad, el controlador no elimina las interfaces de red de ramificación, por lo que deberá eliminarlas por su cuenta. A fin de obtener más información sobre las interfaces de red, consulte Eliminar una interfaz de red en la Guía del usuario de Amazon EC2 para instancias de Linux.

  5. En un terminal separado, se inserta en uno de los Pods. En el resto de este tema, se hace referencia a este terminal como TerminalB. Reemplace 5df6f7687b-4fbjm con el ID de uno de los Pods devueltos en la salida del paso anterior.

    kubectl exec -it -n my-namespace my-deployment-5df6f7687b-4fbjm -- /bin/bash
  6. Desde el intérprete de comandos de TerminalB, confirme que la aplicación de ejemplo funciona.

    curl my-app

    Un ejemplo de salida sería el siguiente.

    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    [...]

    Recibió el resultado porque todos los Pods que se ejecutan en la aplicación están asociados al grupo de seguridad que creó. Ese grupo contiene una regla que permite todo el tráfico entre todos los Pods al que está asociado el grupo de seguridad. Se permite el tráfico DNS saliente de ese grupo de seguridad al grupo de seguridad del clúster, lo que está asociado a los nodos. Los nodos ejecutan los Pods CoreDNS, en los que sus Pods realizó una búsqueda de nombre.

  7. Desde TerminalA, elimine las reglas del grupo de seguridad que permita la comunicación DNS al grupo de seguridad del clúster del grupo de seguridad. Si no agregó las reglas DNS al grupo de seguridad del clúster en un paso anterior, sustituya $my_cluster_security_group_id con el ID del grupo de seguridad en el que creó las reglas.

    aws ec2 revoke-security-group-ingress --group-id $my_cluster_security_group_id --security-group-rule-ids $my_tcp_rule_id aws ec2 revoke-security-group-ingress --group-id $my_cluster_security_group_id --security-group-rule-ids $my_udp_rule_id
  8. Desde TerminalB, intente acceder de nuevo a la aplicación.

    curl my-app

    Un ejemplo de salida sería el siguiente.

    curl: (6) Could not resolve host: my-app

    El intento falla porque el Pod ya no puede acceder a los Pods CoreDNS, que tienen asociado el grupo de seguridad del clúster. El grupo de seguridad del clúster ya no tiene las reglas del grupo de seguridad que permiten la comunicación DNS desde el grupo de seguridad asociado a su Pod.

    Si intenta acceder a la aplicación utilizando las direcciones IP devueltas para uno de los Pods en un paso anterior, sigue recibiendo una respuesta dado que todos los puertos están permitidos entre Pods que tienen el grupo de seguridad asociado a ellos y no es necesaria una búsqueda de nombres.

  9. Una vez que haya terminado de experimentar, puede eliminar la política de grupo de seguridad, la aplicación y el grupo de seguridad de ejemplo que creó. Ejecute los siguientes comandos desde la TerminalA.

    kubectl delete namespace my-namespace aws ec2 revoke-security-group-ingress --group-id $my_pod_security_group_id --security-group-rule-ids $my_inbound_self_rule_id wait sleep 45s aws ec2 delete-security-group --group-id $my_pod_security_group_id