Skip to content

EKS Cluster 创建测验 - 第 2 部分

本测验测试你对 Amazon EKS cluster 创建相关的高级概念、安全设置和网络配置的理解。内容涵盖 cluster 安全、network policies 和 service accounts 等主题。

基础概念问题

  1. 在 Amazon EKS cluster 中,IRSA (IAM Roles for Service Accounts) 的主要用途是什么?
    • A) 向 cluster 管理员授予 IAM 权限
    • B) 将 IAM roles 分配给 worker nodes
    • C) 向 Kubernetes service accounts 授予 AWS service 访问权限
    • D) 向 EKS control plane 授予 IAM 权限
显示答案

答案:C) 向 Kubernetes service accounts 授予 AWS service 访问权限

解释: IRSA (IAM Roles for Service Accounts) 的主要用途是向 Kubernetes service accounts 授予 AWS service 访问权限。此功能允许你在 pod 级别提供细粒度权限,并且不用共享 node 级别的 IAM roles,而是只向每个应用授予所需的最低权限。

IRSA 的工作方式:

  1. OpenID Connect (OIDC) Provider 设置:

    • EKS cluster 被配置为 OIDC provider。
    • 这使 Kubernetes service account tokens 能够成为 AWS IAM 中受信任的身份验证机制。
    bash
    # Associate OIDC provider
    eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve
  2. 创建 IAM Role 并配置 Trust Policy:

    • 创建 Kubernetes service account 可以 assume 的 IAM role。
    • trust policy 限制只有特定 namespaces 中的特定 service accounts 可以 assume 该 role。
    json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.region.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
          },
          "Action": "sts:AssumeRoleWithWebIdentity",
          "Condition": {
            "StringEquals": {
              "oidc.eks.region.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-service-account"
            }
          }
        }
      ]
    }
  3. 创建 Service Account 并关联 IAM Role:

    • 将 IAM role ARN 作为 annotation 添加到 service account。
    yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-service-account
      namespace: default
      annotations:
        eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-role
  4. 在 Pod 中使用 Service Account:

    • 在 pod manifest 中指定 service account。
    yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      serviceAccountName: my-service-account
      containers:
      - name: my-container
        image: my-image

IRSA 的优势:

  1. 最小权限原则:
    • 你可以只向每个应用授予所需的最低权限。
    • 按 pod 设置不同权限,而不是共享 node 级别的 IAM roles
  2. 增强安全性:
    • 无需在代码或环境变量中存储 AWS credentials。
    • 降低 credentials 泄露风险
  3. 权限隔离:
    • 运行在同一 node 上的不同 pods 可以拥有不同的 IAM 权限。
    • 在多租户环境中很重要
  4. 简化 Credential 管理:
    • 无需直接管理 AWS credentials。
    • Credential rotation 会自动处理。

使用 eksctl 设置 IRSA 的示例:

bash
# Create service account and IAM role
eksctl create iamserviceaccount \
  --name my-service-account \
  --namespace default \
  --cluster my-cluster \
  --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
  --approve

# Verify created service account
kubectl get serviceaccount my-service-account -o yaml

其他选项的问题:

  • 向 cluster 管理员授予 IAM 权限: 这不是 IRSA 的用途。Cluster 管理员权限通常通过 aws-auth ConfigMap 管理。
  • 将 IAM roles 分配给 worker nodes: 这是通过 node IAM roles 完成的,与 IRSA 分开。Node IAM roles 会被所有 pods 共享,这可能违反最小权限原则。
  • 向 EKS control plane 授予 IAM 权限: EKS control plane 权限通过 cluster IAM role 管理,与 IRSA 无关。

IRSA 是一项重要功能,它允许 Kubernetes workloads 安全地访问 AWS services,也是在 EKS clusters 上运行应用时推荐的方法。

2. Amazon EKS cluster 中 security groups 的主要作用是什么? - A) 控制 pods 之间的 network traffic - B) 控制 cluster API server 与 nodes 之间的 traffic - C) 应用 Kubernetes RBAC policies - D) 管理用户身份验证

显示答案

答案:B) 控制 cluster API server 与 nodes 之间的 traffic

解释: Amazon EKS cluster 中 security groups 的主要作用是控制 cluster API server 与 nodes 之间的 traffic。Security groups 是 AWS 虚拟防火墙,用于在 EC2 instance 级别控制入站和出站 traffic。在 EKS 中,有 cluster security groups 和 node security groups,它们保护 cluster components 之间的通信。

EKS Clusters 中 Security Groups 的类型:

  1. Cluster Security Group:
    • 应用于 EKS control plane。
    • 允许 worker nodes 与 control plane 之间通信。
    • 创建 EKS cluster 时默认自动创建。
    • 关键规则:
      • 允许来自 node security group 的 443 端口入站 traffic
      • 允许出站 traffic 到 node security group
  2. Node Security Group:
    • 应用于 worker nodes。
    • 允许 nodes 之间以及 nodes 与 control plane 之间通信。
    • 关键规则:
      • 允许 nodes 之间的所有 traffic
      • 允许 443 端口出站 traffic 到 cluster security group
      • 允许来自 cluster security group 的入站 traffic
      • 为 kubelet 允许 10250 端口

Security Group 配置示例:

Cluster Security Group Rules:

Inbound:
- Protocol: TCP
- Port Range: 443
- Source: Node Security Group

Outbound:
- Protocol: All Traffic
- Port Range: All Ports
- Destination: 0.0.0.0/0

Node Security Group Rules:

Inbound:
- Protocol: All Traffic
- Source: Node Security Group itself (node-to-node communication)

- Protocol: TCP
- Port Range: 10250
- Source: Cluster Security Group (kubelet communication)

Outbound:
- Protocol: All Traffic
- Port Range: All Ports
- Destination: 0.0.0.0/0

自定义 Security Groups:

创建 EKS cluster 时可以指定自定义 security groups:

bash
# Specifying custom security groups using AWS CLI
aws eks create-cluster \
  --name my-cluster \
  --role-arn arn:aws:iam::123456789012:role/EksClusterRole \
  --resources-vpc-config subnetIds=subnet-12345,subnet-67890,securityGroupIds=sg-12345

# Specifying custom security groups using eksctl
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: my-cluster
  region: us-west-2
vpc:
  id: vpc-12345
  securityGroup: sg-12345
  subnets:
    private:
      us-west-2a: subnet-12345
      us-west-2b: subnet-67890

Pods 的 Security Groups:

最近,EKS 还支持 pod 级别的 security groups(SecurityGroupsForPods 功能)。这允许你将 security groups 应用于单个 pods:

yaml
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
  name: my-security-group-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: my-app
  securityGroups:
    groupIds:
      - sg-12345

其他选项的问题:

  • 控制 pods 之间的 network traffic: 默认情况下,pods 之间的 network traffic 通过 Kubernetes Network Policies (NetworkPolicy) 控制,而不是 AWS security groups。虽然 SecurityGroupsForPods 功能允许在 pod 级别应用 security groups,但这不是 security groups 的主要作用。
  • 应用 Kubernetes RBAC policies: RBAC (Role-Based Access Control) 是控制 Kubernetes API resources 访问的机制,与 AWS security groups 分开。
  • 管理用户身份验证: EKS clusters 中的用户身份验证通过 AWS IAM 与 Kubernetes RBAC 的集成管理,与 security groups 无关。

Security groups 在 EKS clusters 的网络安全中发挥重要作用,保护 cluster components 之间的通信并阻止不必要的 traffic。正确的 security group 配置对于强化 EKS clusters 的安全态势至关重要。

  1. 在 Amazon EKS cluster 中实现 Kubernetes Network Policies 需要什么?
    • A) AWS security group 配置
    • B) 支持 network policies 的 CNI plugin,例如 Calico 或 Cilium
    • C) AWS Network Firewall 设置
    • D) 启用 VPC Flow Logs
显示答案

答案:B) 支持 network policies 的 CNI plugin,例如 Calico 或 Cilium

解释: 要在 Amazon EKS cluster 中实现 Kubernetes Network Policies,你需要一个支持 network policies 的 CNI (Container Network Interface) plugin,例如 Calico 或 Cilium。默认的 Amazon VPC CNI plugin 不支持 network policies,因此必须安装额外组件。

支持 Network Policy 的 CNI 选项:

  1. Calico:
    • 广泛使用的开源 networking 和 network security 解决方案

    • 可在 EKS 中与 Amazon VPC CNI 一起使用

    • 安装方法:

      bash
      # Install Calico using Helm
      helm repo add projectcalico https://docs.projectcalico.org/charts
      helm install calico projectcalico/tigera-operator --namespace tigera-operator --create-namespace
      
      # Or install using manifest files
      kubectl apply -f https://docs.projectcalico.org/manifests/calico-vxlan.yaml
  2. Cilium:
    • 基于 eBPF 的 networking、安全和可观测性解决方案

    • 提供高性能和高级功能

    • 安装方法:

      bash
      # Install Cilium using Helm
      helm repo add cilium https://helm.cilium.io/
      helm install cilium cilium/cilium --namespace kube-system
  3. AWS CNI with Cilium:
    • 同时使用 Amazon VPC CNI 和 Cilium 的混合方法

    • VPC CNI 处理 pod networking,Cilium 处理 network policies

    • 安装方法:

      bash
      # Install Cilium in network policy only mode
      helm install cilium cilium/cilium --namespace kube-system \
        --set enableIPv4Masquerade=false \
        --set tunnel=disabled \
        --set installIptablesRules=false \
        --set autoDirectNodeRoutes=false \
        --set policyEnforcementMode=default

Network Policy 示例:

yaml
# Default deny policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

# Allow communication between specific applications
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

验证 Network Policy 实现:

bash
# Verify network policy support
kubectl get pods -n kube-system | grep -E 'calico|cilium'

# Apply test network policy
kubectl apply -f test-network-policy.yaml

# Test connectivity
kubectl run -it --rm --restart=Never busybox --image=busybox -- wget -O- --timeout=2 http://service-name

其他选项的问题:

  • AWS security group 配置: AWS security groups 在 EC2 instance 级别工作,不能用于在 Kubernetes pods 之间实现细粒度 network policies。虽然 SecurityGroupsForPods 功能允许将 security groups 应用于 pods,但这是不同于 Kubernetes NetworkPolicy 的机制。
  • AWS Network Firewall 设置: AWS Network Firewall 在 VPC 级别工作,不能用于在 Kubernetes pods 之间实现细粒度 network policies。
  • 启用 VPC Flow Logs: VPC Flow Logs 用于监控和记录 network traffic,但不能用于实现 network policies。

Network policies 是控制 microservices 之间通信并增强 Kubernetes clusters 内部安全性的重要工具。要在 EKS 中实现 network policies,必须安装 Calico 或 Cilium 等额外 CNI plugins。

  1. 在 Amazon EKS cluster 中配置 Secrets 加密的正确方式是什么?
    • A) 创建 EKS cluster 时使用 AWS KMS key 启用加密
    • B) 将 Kubernetes Secrets 迁移到 AWS Secrets Manager
    • C) 将所有 Secrets 编码为 Base64
    • D) 将加密 sidecar container 部署到 EKS cluster
显示答案

答案:A) 创建 EKS cluster 时使用 AWS KMS key 启用加密

解释: 在 Amazon EKS cluster 中配置 Secrets 加密的正确方式,是在创建 EKS cluster 时或在现有 cluster 上使用 AWS KMS (Key Management Service) key 启用加密。此方法可确保 Kubernetes Secrets 存储在 etcd 中时被加密。

配置 EKS Secrets 加密的步骤:

  1. 创建 KMS Key 或使用现有 Key:

    bash
    # Create KMS key
    aws kms create-key --description "EKS Secrets Encryption Key"
    
    # Store the created key ID
    KEY_ID=$(aws kms create-key --query KeyMetadata.KeyId --output text)
  2. 创建新 Cluster 时启用加密:

    bash
    # Enable encryption using AWS CLI
    aws eks create-cluster \
      --name my-cluster \
      --role-arn arn:aws:iam::123456789012:role/EksClusterRole \
      --resources-vpc-config subnetIds=subnet-12345,subnet-67890 \
      --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws:kms:region:123456789012:key/'$KEY_ID'"}}]'
    
    # Enable encryption using eksctl
    cat > cluster.yaml << EOF
    apiVersion: eksctl.io/v1alpha5
    kind: ClusterConfig
    metadata:
      name: my-cluster
      region: us-west-2
    secretsEncryption:
      keyARN: arn:aws:kms:us-west-2:123456789012:key/$KEY_ID
    EOF
    
    eksctl create cluster -f cluster.yaml
  3. 在现有 Cluster 上启用加密:

    bash
    # For existing clusters, you cannot update the encryption configuration, so you need to create a new cluster and migrate workloads.
  4. 验证加密配置:

    bash
    # Check cluster information
    aws eks describe-cluster --name my-cluster --query cluster.encryptionConfig

使用加密的 Secrets:

启用加密后,创建和使用 Secrets 的方法不会改变。所有加密和解密都由 EKS control plane 自动处理。

yaml
# Create Secret
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: YWRtaW4=  # base64 encoded "admin"
  password: cGFzc3dvcmQ=  # base64 encoded "password"
bash
# Create Secret
kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=password

# Verify Secret
kubectl get secret my-secret -o yaml

配置 KMS Key 权限:

你需要配置适当的权限,使 EKS cluster 能够使用 KMS key:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowEKSToUseKMSKey",
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    }
  ]
}

其他选项的问题:

  • 将 Kubernetes Secrets 迁移到 AWS Secrets Manager: 这是一种可行方法,但它与标准 Kubernetes Secrets API 的兼容性较低,并且需要额外配置和集成。此外,所有应用都需要修改为从 AWS Secrets Manager 获取 secrets。
  • 将所有 Secrets 编码为 Base64: Kubernetes Secrets 默认已经使用 Base64 编码。但是,Base64 是一种编码方式,不是加密,不能提供安全性。
  • 将加密 sidecar container 部署到 EKS cluster: 这不是标准方法,并且向所有 pods 添加 sidecars 会引入复杂性。它还需要与 Kubernetes API server 集成。

使用 AWS KMS 的 EKS Secrets 加密是保护存储在 etcd 中的 Secrets 的最有效且集成度最高的方式。这让你可以保护静态敏感数据,并利用 AWS 强大的 key management 能力。

5\. 自定义 Amazon EKS cluster 中 worker nodes 的 kubelet 配置的正确方式是什么? - A) 在 EKS console 中修改 cluster 配置 - B) 创建 node group 时使用 --kubelet-extra-args 参数 - C) 使用 kubectl edit node 命令 - D) 使用 AWS Systems Manager 更改 node 配置
显示答案

答案:B) 创建 node group 时使用 --kubelet-extra-args 参数

解释: 自定义 Amazon EKS cluster 中 worker nodes 的 kubelet 配置的正确方式,是在创建 node group 时使用 --kubelet-extra-args 参数。此方法允许你在 node bootstrap 时向 kubelet 传递额外参数。

自定义 kubelet 配置的方法:

  1. 将 Launch Templates 与 Managed Node Groups 一起使用:

    • 在 launch template 的 user data 部分自定义 bootstrap script。
    bash
    #!/bin/bash
    set -o xtrace
    /etc/eks/bootstrap.sh my-cluster \
      --kubelet-extra-args '--max-pods=110 --kube-reserved memory=0.3Gi,cpu=100m --system-reserved memory=0.5Gi,cpu=200m --eviction-hard memory.available<500Mi'
  2. 使用 eksctl 创建 Node Groups:

bash
# Create node group with kubelet arguments
eksctl create nodegroup \
  --cluster my-cluster \
  --name my-nodegroup \
  --node-type m5.large \
  --nodes 3 \
  --kubelet-extra-args "--max-pods=110 --kube-reserved memory=0.3Gi,cpu=100m"
  1. 使用 eksctl 配置文件:

    yaml
    apiVersion: eksctl.io/v1alpha5
    kind: ClusterConfig
    metadata:
      name: my-cluster
      region: us-west-2
    managedNodeGroups:
      - name: my-nodegroup
        instanceType: m5.large
        minSize: 2
        maxSize: 5
        kubeletExtraArgs:
          max-pods: "110"
          kube-reserved: "memory=0.3Gi,cpu=100m"
          system-reserved: "memory=0.5Gi,cpu=200m"
          eviction-hard: "memory.available<500Mi"
  2. 为 self-managed node groups 使用 user data script:

    bash
    #!/bin/bash
    set -o xtrace
    /etc/eks/bootstrap.sh my-cluster \
      --kubelet-extra-args '--max-pods=110 --node-labels=node.kubernetes.io/role=worker,environment=prod'

常见自定义 kubelet 参数:

  1. max-pods:
    • 设置每个 node 的最大 pods 数量
    • 示例:--max-pods=110
  2. node-labels:
    • 向 node 添加 labels
    • 示例:--node-labels=environment=prod,node-type=worker
  3. kube-reserved:
    • 为 Kubernetes system components 预留 resources
    • 示例:--kube-reserved=cpu=100m,memory=0.3Gi,ephemeral-storage=1Gi
  4. system-reserved:
    • 为 OS system daemons 预留 resources
    • 示例:--system-reserved=cpu=100m,memory=0.5Gi,ephemeral-storage=1Gi
  5. eviction-hard:
    • 设置 hard eviction 阈值
    • 示例:--eviction-hard=memory.available<500Mi,nodefs.available<10%
  6. cgroup-driver:
    • 设置 cgroup driver
    • 示例:--cgroup-driver=systemd

如何验证配置:

bash
# SSH into the node
ssh -i ~/.ssh/id_rsa ec2-user@<node-ip>

# Check kubelet service configuration
sudo systemctl status kubelet
sudo cat /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf

# Check running kubelet process arguments
ps aux | grep kubelet

其他选项的问题:

  • 在 EKS console 中修改 cluster 配置: 虽然 EKS console 允许你修改 cluster 级别配置,但它不提供直接修改单个 nodes 的 kubelet 配置的选项。
  • 使用 kubectl edit node 命令: kubectl edit node 命令可以修改 node object metadata,但不能更改 kubelet 配置。kubelet 配置作为 node OS 上的 service 运行,不能通过 Kubernetes API 直接修改。
  • 使用 AWS Systems Manager 更改 node 配置: AWS Systems Manager 可用于在 nodes 上运行命令或更改配置,但此方法是在 nodes 已创建后应用的。此外,更改 kubelet 配置后必须重启 service,这可能影响正在运行的 pods。因此,在 node group 创建时配置更安全,也是推荐方法。

自定义 kubelet 配置允许你优化 node resource 管理、pod 密度、eviction policies 等,以满足 workload 需求。但是,这些更改可能影响 cluster 稳定性,因此应仔细测试。

  1. Amazon EKS clusters 中替代 Pod Security Policy 的推荐机制是什么?
    • A) AWS Security Hub
    • B) Pod Security Admission 或 Kyverno 等 policy engines
    • C) AWS Config Rules
    • D) EKS Security Groups
显示答案

答案:B) Pod Security Admission 或 Kyverno 等 policy engines

解释: 在 Amazon EKS clusters 中替代 Pod Security Policy (PSP) 的推荐机制是 Pod Security Admission 或 Kyverno 等 policy engines。从 Kubernetes 1.21 开始,PSP 被弃用,并在 Kubernetes 1.25 中被完全移除。Pod Security Admission 作为替代方案引入,也可以使用 Kyverno 或 OPA Gatekeeper 等 policy engines 作为替代。

Pod Security Admission:

Pod Security Admission 从 Kubernetes 1.23 开始作为 beta 功能引入,并在 1.25 版本中成为稳定功能。它是内置 Kubernetes 功能,提供三个安全级别(Privileged、Baseline、Restricted)。

  1. 配置方法:

    yaml
    # Apply Pod Security standards to namespace
    apiVersion: v1
    kind: Namespace
    metadata:
      name: my-namespace
      labels:
        pod-security.kubernetes.io/enforce: restricted
        pod-security.kubernetes.io/audit: restricted
        pod-security.kubernetes.io/warn: restricted
  2. 安全级别:

    • Privileged: 无限制,允许所有功能
    • Baseline: 防止已知的 privilege escalations
    • Restricted: 强安全加固,应用最小权限原则
  3. 模式:

    • enforce: 发生违规时拒绝创建 pod
    • audit: 在 audit logs 中记录违规
    • warn: 发生违规时显示 warning messages

Kyverno:

Kyverno 是 Kubernetes-native policy engine,使用基于 YAML 的 policies 来验证、变更和生成 cluster resources。

  1. 安装方法:

    bash
    # Install Kyverno using Helm
    helm repo add kyverno https://kyverno.github.io/kyverno/
    helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace
  2. Policy 示例:

    yaml
    # Policy to prevent privileged containers
    apiVersion: kyverno.io/v1
    kind: ClusterPolicy
    metadata:
      name: disallow-privileged-containers
    spec:
      validationFailureAction: enforce
      rules:
      - name: privileged-containers
        match:
          resources:
            kinds:
            - Pod
        validate:
          message: "Privileged containers are not allowed"
          pattern:
            spec:
              containers:
              - name: "*"
                securityContext:
                  privileged: false

OPA Gatekeeper:

OPA (Open Policy Agent) Gatekeeper 是 Kubernetes 中另一个流行的 policy management 解决方案。

  1. 安装方法:

    bash
    # Install Gatekeeper
    kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
  2. Policy 示例:

    yaml
    # ConstraintTemplate definition
    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8spsprivilegedcontainer
    spec:
      crd:
        spec:
          names:
            kind: K8sPSPPrivilegedContainer
      targets:
      - target: admission.k8s.gatekeeper.sh
        rego: |
          package k8spsprivilegedcontainer
          violation[{"msg": msg}] {
            c := input.review.object.spec.containers[_]
            c.securityContext.privileged
            msg := sprintf("Privileged container is not allowed: %v", [c.name])
          }
    
    # Apply Constraint
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
      name: psp-privileged-container
    spec:
      match:
        kinds:
        - apiGroups: [""]
          kinds: ["Pod"]

EKS 的实施建议:

  1. 启用 Pod Security Admission:
    • 在 EKS 1.23 及以上版本中默认可用
    • 向 namespaces 应用适当的 labels
  2. 安装 Kyverno 或 Gatekeeper:
    • 当需要更复杂 policies 时
    • 当需要对多种 resource types 应用 policies 时
  3. 逐步迁移:
    • 从 PSP 逐步迁移到新解决方案
    • 从 audit 模式开始识别问题,然后切换到 enforce 模式

其他选项的问题:

  • AWS Security Hub: AWS Security Hub 是用于监控 AWS resources 安全态势的 service,但不能用于在 Kubernetes 中应用 pod 级别的 security policies。
  • AWS Config Rules: AWS Config 是用于评估 AWS resource configurations 的 service,但不能用于在 Kubernetes 中应用 pod 级别的 security policies。
  • EKS Security Groups: EKS Security Groups 用于控制 network traffic,不能用于限制 pod security contexts 或 privileges。

随着 Pod Security Policy (PSP) 被移除,EKS clusters 应使用 Pod Security Admission、Kyverno 或 OPA Gatekeeper 等替代机制来强化 pod 安全。这些工具可以限制 privileged containers、host namespace access、host path mounts 等。

7. 配置 IRSA (IAM Roles for Service Accounts) 以在 Amazon EKS cluster 中将 pod identity 与 AWS IAM 集成的第一步是什么? - A) 创建 IAM role - B) 创建 service account - C) 关联 OIDC provider - D) 修改 pod manifest

显示答案

答案:C) 关联 OIDC provider

解释: 在 Amazon EKS cluster 中配置 IRSA (IAM Roles for Service Accounts) 的第一步是关联 OIDC (OpenID Connect) provider。OIDC provider 是在 AWS IAM 与 Kubernetes service accounts 之间建立信任关系所必需的。这允许 Kubernetes service account tokens 成为 AWS IAM 中受信任的身份验证机制。

IRSA 配置步骤顺序:

  1. 关联 OIDC provider:

    • 检查 EKS cluster 的 OIDC issuer URL
    • 在 AWS IAM 中创建 OIDC provider
    bash
    # Check OIDC issuer URL
    aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text
    # Example output: https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE
    
    # Associate OIDC provider
    eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve
    
    # Or use AWS CLI
    aws iam create-open-id-connect-provider \
      --url https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE \
      --thumbprint-list 9e99a48a9960b14926bb7f3b02e22da2b0ab7280 \
      --client-id-list sts.amazonaws.com
  2. 创建 IAM role:

    • 创建 service account 将要 assume 的 IAM role
    • 在 trust policy 中包含 OIDC provider 和 service account 条件
    json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
          },
          "Action": "sts:AssumeRoleWithWebIdentity",
          "Condition": {
            "StringEquals": {
              "oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:default:my-service-account"
            }
          }
        }
      ]
    }
  3. 创建 service account:

    • 创建带有 IAM role ARN annotation 的 service account
    yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-service-account
      namespace: default
      annotations:
        eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-role
  4. 修改 pod manifest:

    • 在 pod manifest 中指定 service account
    yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      serviceAccountName: my-service-account
      containers:
      - name: my-container
        image: my-image

使用 eksctl 简化 IRSA 设置:

eksctl 提供可自动完成上述所有步骤的命令:

bash
# Associate OIDC provider
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve

# Create service account and IAM role
eksctl create iamserviceaccount \
  --name my-service-account \
  --namespace default \
  --cluster my-cluster \
  --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
  --approve

验证 IRSA 是否正常工作:

bash
# Check service account
kubectl get serviceaccount my-service-account -o yaml

# Run test pod
kubectl run -it --rm \
  --image amazon/aws-cli \
  --serviceaccount my-service-account \
  aws-cli -- s3 ls

其他选项的问题:

  • 创建 IAM role: 创建 IAM role 是 IRSA 配置的第二步。必须先关联 OIDC provider,这样 IAM role 的 trust policy 才能引用 OIDC provider。
  • 创建 service account: 创建 service account 是 IRSA 配置的第三步。必须先创建 IAM role,这样才能将 IAM role ARN 作为 annotation 添加到 service account。
  • 修改 pod manifest: 修改 pod manifest 是 IRSA 配置的最后一步。必须先创建 service account,这样 pod 才能引用该 service account。

IRSA 是一种安全且高效的方式,用于向 Kubernetes workloads 授予对 AWS services 的细粒度权限。这让你可以向每个应用只授予所需的最低权限,而不是共享 node 级别的 IAM roles。IRSA 配置的第一步是关联 OIDC provider,这对于建立 AWS IAM 与 Kubernetes service accounts 之间的信任关系至关重要。

  1. 在 Amazon EKS cluster 中启用 control plane logs 的正确方式是什么?
    • A) 在 EKS control plane 上安装 CloudWatch agent
    • B) 通过 AWS CLI 或 console 启用 cluster logging 配置
    • C) 使用 Fluentd 配置 log forwarding
    • D) SSH 到 EKS control plane nodes 修改 log 配置
显示答案

答案:B) 通过 AWS CLI 或 console 启用 cluster logging 配置

解释: 在 Amazon EKS cluster 中启用 control plane logs 的正确方式,是通过 AWS CLI 或 AWS Management Console 启用 cluster logging 配置。由于 EKS 是 managed service,control plane 由 AWS 管理,因此你无法直接访问它或安装 agents。相反,必须通过 AWS 提供的 APIs 配置 logging。

使用 AWS CLI 启用 control plane logs:

bash
# Enable all log types
aws eks update-cluster-config \
  --name my-cluster \
  --region us-west-2 \
  --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'

# Enable only specific log types
aws eks update-cluster-config \
  --name my-cluster \
  --region us-west-2 \
  --logging '{"clusterLogging":[{"types":["api","audit"],"enabled":true},{"types":["authenticator","controllerManager","scheduler"],"enabled":false}]}'

使用 eksctl 启用 control plane logs:

bash
# Enable all log types
eksctl utils update-cluster-logging \
  --enable-types api,audit,authenticator,controllerManager,scheduler \
  --cluster my-cluster \
  --region us-west-2

# Enable only specific log types
eksctl utils update-cluster-logging \
  --enable-types api,audit \
  --disable-types authenticator,controllerManager,scheduler \
  --cluster my-cluster \
  --region us-west-2

使用 AWS Management Console 启用 control plane logs:

  1. 登录 AWS Management Console。
  2. 导航到 EKS service。
  3. 从 cluster 列表中选择目标 cluster。
  4. 选择 "Logging" tab。
  5. 点击 "Manage"。
  6. 选择要启用的 log types:
    • API server (api)
    • Audit (audit)
    • Authenticator (authenticator)
    • Controller manager (controllerManager)
    • Scheduler (scheduler)
  7. 点击 "Save changes"。

可用的 log types:

  1. API server (api):
    • 来自 Kubernetes API server 的 logs
    • 包含 API request 和 response 信息
  2. Audit (audit):
    • cluster 中所有活动的 audit logs
    • 对安全和合规目的很重要
  3. Authenticator (authenticator):
    • 来自 AWS IAM Authenticator 的 logs
    • 有助于排查身份验证问题
  4. Controller manager (controllerManager):
    • 来自 Kubernetes controller manager 的 logs
    • 包含 resource state management 信息
  5. Scheduler (scheduler):
    • 来自 Kubernetes scheduler 的 logs
    • 包含 pod scheduling 决策信息

如何查看 logs:

启用的 logs 存储在 CloudWatch Logs 中,可以在以下 log group 中查看:

/aws/eks/my-cluster/cluster

每种 log type 都作为单独的 log stream 存储:

kube-apiserver-xxxxx
audit-xxxxx
authenticator-xxxxx
kube-controller-manager-xxxxx
kube-scheduler-xxxxx

成本注意事项:

  • Control plane logs 受 CloudWatch Logs pricing 约束。
  • 启用所有 log types 可能会生成大量 logs。
  • 为优化成本,建议只选择性启用所需的 log types。
  • 可以通过设置适当的 log retention periods 来管理成本。

其他选项的问题:

  • 在 EKS control plane 上安装 CloudWatch agent: EKS control plane 由 AWS 管理,因此你无法直接访问它或安装 agents。
  • 使用 Fluentd 配置 log forwarding: Fluentd 可用于收集 worker nodes 的 logs,但不能访问 EKS control plane logs。
  • SSH 到 EKS control plane nodes 修改 log 配置: EKS control plane nodes 由 AWS 管理,因此你不能直接 SSH 进入它们。

EKS control plane logs 为 cluster troubleshooting、security audits 和 compliance 提供重要信息。你可以通过 AWS CLI 或 AWS Management Console 选择性启用所需的 log types 来有效监控。

  1. 更改 Amazon EKS cluster 中 node group instance type 的正确方式是什么?
    • A) 在 AWS Management Console 中直接修改 node group instance type
    • B) 使用新的 instance type 创建新 node group 并迁移 workloads
    • C) 使用 kubectl edit 命令修改 node specifications
    • D) 使用 AWS CLI update-nodegroup-config 命令
显示答案

答案:B) 使用新的 instance type 创建新 node group 并迁移 workloads

解释: 更改 Amazon EKS cluster 中 node group instance type 的正确方式,是使用新的 instance type 创建新的 node group,然后迁移 workloads。在 EKS managed node groups 中,创建后无法直接更改 instance type,因此必须创建新的 node group、迁移 workloads,然后删除现有 node group。

更改 node group instance type 的步骤:

  1. 创建新 node group:

    bash
    # Create new node group using eksctl
    eksctl create nodegroup \
      --cluster my-cluster \
      --name my-new-nodegroup \
      --node-type m5.large \
      --nodes 3 \
      --nodes-min 1 \
     --nodes-max 5 \
     --node-labels "migration-target=true"

Create new node group using AWS CLI

aws eks create-nodegroup
--cluster-name my-cluster
--nodegroup-name my-new-nodegroup
--subnets subnet-12345 subnet-67890
--instance-types m5.large
--scaling-config minSize=1,maxSize=5,desiredSize=3
--node-role arn:aws:iam::123456789012:role/EksNodeRole
--labels migration-target=true


2. **验证新 node group 状态**:
 ```bash
 # Check node group status
 aws eks describe-nodegroup \
   --cluster-name my-cluster \
   --nodegroup-name my-new-nodegroup \
   --query "nodegroup.status"

 # Check nodes
 kubectl get nodes --label-columns migration-target
  1. 迁移 workloads:

    方法 1:使用 Cordoning 和 Draining

    bash
    # Identify nodes in the existing node group
    OLD_NODES=$(kubectl get nodes -l alpha.eksctl.io/nodegroup-name=my-old-nodegroup -o jsonpath='{.items[*].metadata.name}')
    
    # Cordon nodes (prevent new pod scheduling)
    for node in $OLD_NODES; do
      kubectl cordon $node
    done
    
    # Drain nodes (remove existing pods)
    for node in $OLD_NODES; do
      kubectl drain $node --ignore-daemonsets --delete-emptydir-data
    done

    方法 2:使用 Pod Selector

    yaml
    # Deploy to new nodes using node selector
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-app
    spec:
      template:
        spec:
          nodeSelector:
            migration-target: "true"

    方法 3:Blue/Green Deployment

    • 将新的 deployment version 部署到新 node group
    • 逐步将 traffic 切换到新 version
    • 移除现有 deployment version
  2. 删除现有 node group:

    bash
    # Delete node group using eksctl
    eksctl delete nodegroup \
      --cluster my-cluster \
      --name my-old-nodegroup
    
    # Delete node group using AWS CLI
    aws eks delete-nodegroup \
      --cluster-name my-cluster \
      --nodegroup-name my-old-nodegroup

迁移期间的注意事项:

  1. 最小化 workload 中断:

    • 配置 PodDisruptionBudget
    yaml
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: my-app-pdb
    spec:
      minAvailable: 2  # or maxUnavailable: 1
      selector:
        matchLabels:
          app: my-app
    • 使用 rolling update strategy
  2. Resource 需求:

    • 验证新 instance type 是否满足 workload 需求
    • 考虑 CPU、memory、storage 和 networking 需求
  3. Stateful workloads:

    • 验证使用 persistent volumes 的 workloads 的数据持久性
    • 必要时执行 backups
  4. 成本影响:

    • 评估新 instance type 的成本影响
    • 迁移期间两个 node groups 同时运行,成本会暂时增加

其他选项的问题:

  • 在 AWS Management Console 中直接修改 node group instance type: 在 EKS managed node groups 中,创建后不能直接修改 instance type。
  • 使用 kubectl edit 命令修改 node specifications: kubectl 用于修改 Kubernetes API objects,但 node 的底层 instance type 在 AWS infrastructure 级别确定,不能通过 kubectl 更改。
  • 使用 AWS CLI update-nodegroup-config 命令: update-nodegroup-config 命令可以修改 node group 的 scaling configuration、labels、taints 等,但不能更改 instance type。

为了优化 cluster 性能、降低成本或满足新的 workload 需求,可能需要更改 node group 的 instance type。创建新 node group 并迁移 workloads 是在尽量减少中断的同时安全更改 instance types 的推荐方法。

10. 在 Amazon EKS cluster 中将 Kubernetes taints 应用于 node group 的正确方式是什么? - A) 使用 kubectl taint 命令 - B) 创建 node group 时使用 --taints 参数 - C) 在 AWS Management Console 中配置 node group taints - D) 在 node bootstrap script 中修改 kubelet 配置

显示答案

答案:B) 创建 node group 时使用 --taints 参数

解释: 在 Amazon EKS cluster 中将 Kubernetes taints 应用于 node group 的正确方式,是在创建 node group 时使用 --taints 参数。EKS managed node groups 提供在创建时或更新期间配置 taints 的能力。使用此方法可确保 taints 一致地应用到 node group 中的所有 nodes,并在 nodes 被替换时保持。

使用 eksctl 配置 taints:

bash
# Create node group with taints
eksctl create nodegroup \
  --cluster my-cluster \
  --name tainted-ng \
  --node-type m5.large \
  --nodes 3 \
  --taints "dedicated=gpu:NoSchedule,special=true:PreferNoSchedule"

# Configure taints using configuration file
cat > nodegroup.yaml << EOF
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: my-cluster
  region: us-west-2
managedNodeGroups:
  - name: tainted-ng
    instanceType: m5.large
    minSize: 2
    maxSize: 5
    taints:
      - key: dedicated
        value: gpu
        effect: NoSchedule
      - key: special
        value: "true"
        effect: PreferNoSchedule
EOF

eksctl create nodegroup -f nodegroup.yaml

使用 AWS CLI 配置 taints:

bash
# Create node group with taints
aws eks create-nodegroup \
  --cluster-name my-cluster \
  --nodegroup-name tainted-ng \
  --subnets subnet-12345 subnet-67890 \
  --instance-types m5.large \
  --scaling-config minSize=2,maxSize=5,desiredSize=3 \
  --node-role arn:aws:iam::123456789012:role/EksNodeRole \
  --taints "key=dedicated,value=gpu,effect=NoSchedule" "key=special,value=true,effect=PreferNoSchedule"

# Update taints on existing node group
aws eks update-nodegroup-config \
  --cluster-name my-cluster \
  --nodegroup-name tainted-ng \
  --taints "addOrUpdateTaints=[{key=dedicated,value=gpu,effect=NoSchedule}],removeTaints=[{key=special}]"

使用 AWS Management Console 配置 taints:

  1. 登录 AWS Management Console。
  2. 导航到 EKS service。
  3. 选择 cluster。
  4. 选择 "Compute" tab。
  5. 点击 "Add node group"。
  6. 输入 node group details。
  7. 在 "Kubernetes taints" 部分,点击 "Add taint"。
  8. 输入 key、value 和 effect。
  9. 点击 "Create"。

Taint effect 类型:

  1. NoSchedule:
    • 没有匹配 toleration 的 Pods 不会被调度到该 node。
    • 现有 pods 不受影响。
  2. PreferNoSchedule:
    • 没有匹配 toleration 的 Pods 最好不要被调度到该 node,但不保证。
    • 如果它们无法调度到其他 nodes,则可能会被调度到此 node。
  3. NoExecute:
    • 没有匹配 toleration 的 Pods 不会被调度到该 node。
    • 已经运行但没有匹配该 taint 的 toleration 的 Pods 将被 evicted。

taints 的常见使用场景:

  1. 隔离特殊硬件 nodes:

    bash
    # Apply taint to GPU nodes
    eksctl create nodegroup \
      --cluster my-cluster \
      --name gpu-nodes \
      --node-type p3.2xlarge \
      --taints "dedicated=gpu:NoSchedule"
    
    # Add toleration to GPU workload
    apiVersion: v1
    kind: Pod
    metadata:
      name: gpu-pod
    spec:
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "gpu"
        effect: "NoSchedule"
      containers:
      - name: gpu-container
        image: gpu-image
  2. 准备 node maintenance:

    bash
    # Apply taint to node
    kubectl taint nodes node1 maintenance=planned:NoSchedule
    
    # Remove taint after maintenance
    kubectl taint nodes node1 maintenance=planned:NoSchedule-
  3. 为特定 workloads 配置 dedicated nodes:

    bash
    # Node group dedicated to production workloads
    eksctl create nodegroup \
      --cluster my-cluster \
      --name prod-nodes \
      --node-type m5.large \
      --taints "environment=production:NoSchedule"
    
    # Add toleration to production deployment
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: prod-app
    spec:
      template:
        spec:
          tolerations:
          - key: "environment"
            operator: "Equal"
            value: "production"
            effect: "NoSchedule"

其他选项的问题:

  • 使用 kubectl taint 命令: 你可以使用 kubectl taint 命令向单个 nodes 应用 taints,但这是临时更改,nodes 被替换时 taints 不会保持。它也难以一致地应用到 node group 中的所有 nodes。
  • 在 AWS Management Console 中配置 node group taints: 你也可以在 AWS Management Console 中创建 node group 时配置 taints,但这与“创建 node group 时使用 --taints 参数”是同一种方法。因此,该选项也可能是正确答案,但从技术上讲,它与创建 node group 时配置 taints 相同。
  • 在 node bootstrap script 中修改 kubelet 配置: 你可以在 bootstrap script 中使用 --register-with-taints flag 修改 kubelet 配置,但这种方法复杂且容易出错。对于 EKS managed node groups 也不推荐使用。

Taints 是一个有用的 Kubernetes 功能,可用于只将特定 workloads 部署到特定 nodes,或将某些 workloads 从特定 nodes 排除。对于 EKS managed node groups,在创建或更新 node group 时配置 taints 是最有效且最易管理的方法。

## 动手练习

练习 1:配置 IRSA (IAM Roles for Service Accounts)

场景: 你有一个运行在 EKS cluster 中的应用,需要访问 S3 bucket。遵循安全最佳实践,你希望使用 IRSA 只向特定 pods 授予必要权限,而不是共享 node IAM role。

要求:

  1. 关联 OIDC provider
  2. 创建具有 S3 访问权限的 IAM role
  3. 创建 service account 并关联 IAM role
  4. 部署使用该 service account 的 pod
  5. 测试 S3 访问

解答:

显示解答

1. 关联 OIDC Provider

bash
# Get the cluster's OIDC issuer URL
OIDC_PROVIDER=$(aws eks describe-cluster --name my-cluster --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///")

# Check if OIDC provider already exists
aws iam list-open-id-connect-providers | grep $OIDC_PROVIDER

# Create OIDC provider if it doesn't exist
eksctl utils associate-iam-oidc-provider --cluster my-cluster --approve

2. 创建具有 S3 访问权限的 IAM Role

bash
# Create trust policy
cat > trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):oidc-provider/${OIDC_PROVIDER}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "${OIDC_PROVIDER}:sub": "system:serviceaccount:default:s3-access-sa"
        }
      }
    }
  ]
}
EOF

# Create IAM role
aws iam create-role --role-name s3-access-role --assume-role-policy-document file://trust-policy.json

# Attach S3 access policy
aws iam attach-role-policy --role-name s3-access-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

3. 创建 Service Account 并关联 IAM Role

bash
# Get IAM role ARN
ROLE_ARN=$(aws iam get-role --role-name s3-access-role --query Role.Arn --output text)

# Create service account
cat > service-account.yaml << EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: s3-access-sa
  namespace: default
  annotations:
    eks.amazonaws.com/role-arn: ${ROLE_ARN}
EOF

kubectl apply -f service-account.yaml

4. 部署使用该 Service Account 的 Pod

bash
# Deploy test pod
cat > pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
  name: s3-access-pod
  namespace: default
spec:
  serviceAccountName: s3-access-sa
  containers:
  - name: aws-cli
    image: amazon/aws-cli:latest
    command:
    - sleep
    - "3600"
  restartPolicy: Never
EOF

kubectl apply -f pod.yaml

5. 测试 S3 访问

bash
# Verify the pod is running
kubectl get pod s3-access-pod

# Test listing S3 buckets
kubectl exec -it s3-access-pod -- aws s3 ls

# Test listing objects in a specific S3 bucket
kubectl exec -it s3-access-pod -- aws s3 ls s3://my-bucket

# Verify AWS credentials
kubectl exec -it s3-access-pod -- aws sts get-caller-identity

6. 清理

bash
# Delete pod
kubectl delete pod s3-access-pod

# Delete service account
kubectl delete serviceaccount s3-access-sa

# Clean up IAM role
aws iam detach-role-policy --role-name s3-access-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam delete-role --role-name s3-access-role

补充说明:

  1. OIDC Provider 关联:
    • OIDC provider 在 AWS IAM 与 Kubernetes service accounts 之间建立信任关系。
    • 每个 cluster 只需要设置一次。
  2. IAM Role Trust Policy:
    • trust policy 限制只有特定 namespaces 中的特定 service accounts 可以 assume 该 role。
    • 使用 condition statements 增强安全性。
  3. Service Account Annotation:
    • eks.amazonaws.com/role-arn annotation 指定 service account 将 assume 的 IAM role。
    • 此 annotation 由 EKS Pod Identity Webhook 处理。
  4. Environment Variables:
    • EKS Pod Identity Webhook 会自动将以下 environment variables 注入 pod:
      • AWS_ROLE_ARN
      • AWS_WEB_IDENTITY_TOKEN_FILE
      • AWS_REGION
    • AWS SDKs 使用这些 environment variables 获取 credentials。
  5. 最小权限原则:
    • 只授予应用所需的最低权限。
    • 在此示例中,只授予了 S3 read-only access 权限。

通过本练习,你学习了如何配置 IRSA,将对 AWS services 的细粒度权限只授予运行在 EKS cluster 中的特定 pods。这种方法比共享 node IAM role 更安全,并遵循最小权限原则。

### 练习 2:强化 EKS Cluster 安全

场景: 你是公司的安全工程师,需要强化新创建的 EKS cluster 的安全。该 cluster 已使用默认设置创建并配置。你希望根据安全最佳实践加固 cluster。

要求:

  1. 限制 cluster endpoint access
  2. 启用 Secrets encryption
  3. 实现 network policies
  4. 应用 Pod Security Standards
  5. 启用 control plane logging

解答:

显示解答

1. 限制 Cluster Endpoint Access

bash
# Check current cluster endpoint configuration
aws eks describe-cluster --name my-cluster --query "cluster.resourcesVpcConfig.endpointPublicAccess"
aws eks describe-cluster --name my-cluster --query "cluster.resourcesVpcConfig.endpointPrivateAccess"

# Restrict public access (allow only specific CIDR blocks)
aws eks update-cluster-config \
  --name my-cluster \
  --resources-vpc-config endpointPublicAccess=true,endpointPrivateAccess=true,publicAccessCidrs=["203.0.113.0/24","198.51.100.0/24"]

# Or disable public access (private cluster)
aws eks update-cluster-config \
  --name my-cluster \
  --resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true

2. 启用 Secrets Encryption

bash
# Create KMS key
aws kms create-key --description "EKS Secrets Encryption Key"
KEY_ID=$(aws kms create-key --query KeyMetadata.KeyId --output text)

# Add alias to KMS key
aws kms create-alias \
  --alias-name alias/eks-secrets \
  --target-key-id $KEY_ID

# Cannot enable encryption on current cluster, so a new cluster must be created
# Get existing cluster configuration
aws eks describe-cluster --name my-cluster > cluster-config.json

# Create new cluster (more parameters are needed in practice)
aws eks create-cluster \
  --name my-cluster-encrypted \
  --role-arn $(aws eks describe-cluster --name my-cluster --query cluster.roleArn --output text) \
  --resources-vpc-config subnetIds=$(aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.subnetIds --output text | tr -d '[]" ' | tr ',' ' '),securityGroupIds=$(aws eks describe-cluster --name my-cluster --query cluster.resourcesVpcConfig.securityGroupIds --output text | tr -d '[]" ') \
  --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws:kms:'$(aws configure get region)':'$(aws sts get-caller-identity --query Account --output text)':key/'$KEY_ID'"}}]'

3. 实现 Network Policies

bash
# Install Calico
kubectl create namespace tigera-operator
helm repo add projectcalico https://docs.projectcalico.org/charts
helm install calico projectcalico/tigera-operator --namespace tigera-operator

# Create default deny network policy
cat > default-deny.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF

kubectl apply -f default-deny.yaml

# Policy to allow communication between specific applications
cat > allow-app-communication.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080
EOF

kubectl apply -f allow-app-communication.yaml

4. 应用 Pod Security Standards

bash
# Apply Pod Security Standards to namespace
cat > pod-security.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
  name: restricted-ns
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
EOF

kubectl apply -f pod-security.yaml

# Add labels to existing namespace
kubectl label namespace default \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

# Install Kyverno (for additional policy enforcement)
kubectl create namespace kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno --namespace kyverno

# Policy to prevent privileged containers
cat > restrict-privileged.yaml << EOF
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
spec:
  validationFailureAction: enforce
  rules:
  - name: privileged-containers
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "Privileged containers are not allowed"
      pattern:
        spec:
          containers:
          - name: "*"
            securityContext:
              privileged: false
EOF

kubectl apply -f restrict-privileged.yaml

5. 启用 Control Plane Logging

bash
# Enable all control plane log types
aws eks update-cluster-config \
  --name my-cluster \
  --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'

# Verify logging status
aws eks describe-cluster --name my-cluster --query "cluster.logging"

# Check logs in CloudWatch Logs
aws logs describe-log-groups --log-group-name-prefix /aws/eks/my-cluster

6. 其他安全加固措施

bash
# Restrict IAM policy for AWS Load Balancer Controller
cat > alb-controller-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeVpcs",
        "ec2:DescribeSubnets",
        "ec2:DescribeSecurityGroups",
        "elasticloadbalancing:DescribeLoadBalancers",
        "elasticloadbalancing:DescribeTargetGroups",
        "elasticloadbalancing:DescribeListeners"
      ],
      "Resource": "*"
    }
  ]
}
EOF

aws iam create-policy \
  --policy-name EksAlbControllerRestrictedPolicy \
  --policy-document file://alb-controller-policy.json

# Configure node group update for periodic node replacement
aws eks update-nodegroup-config \
  --cluster-name my-cluster \
  --nodegroup-name my-nodegroup \
  --update-config '{"maxUnavailable": 1}'

# Start node group update
aws eks update-nodegroup-version \
  --cluster-name my-cluster \
  --nodegroup-name my-nodegroup

安全加固说明:

  1. 限制 Cluster Endpoint Access:
    • 将 public endpoint access 限制为特定 IP ranges,或完全禁用。
    • 启用 private endpoint 以允许从 VPC 内部访问 cluster。
    • 这可以防止未经授权访问 cluster API server。
  2. 启用 Secrets Encryption:
    • 使用 AWS KMS keys 加密存储在 etcd 中的 Kubernetes Secrets。
    • 保护静态敏感数据。
    • 注意:无法在现有 clusters 上启用加密,因此需要创建新 cluster。
  3. 实现 Network Policies:
    • 安装 Calico 以支持 Kubernetes network policies。
    • 应用 default deny policies 以阻止所有未明确允许的 traffic。
    • 实现只允许必要通信的细粒度 policies。
  4. 应用 Pod Security Standards:
    • 应用 Kubernetes 1.23 及更高版本中可用的 Pod Security Standards。
    • 在 namespace 级别设置 security constraints。
    • 使用 Kyverno 等 policy engines 应用额外 security policies。
  5. 启用 Control Plane Logging:
    • 将所有 control plane log types 发送到 CloudWatch Logs。
    • 通过 audit logs 监控 cluster 活动。
    • 保留 logs 以用于 security events 和 troubleshooting。

通过本动手练习,你学习了多种强化 EKS cluster 安全的方法。这些安全措施有助于提升 cluster 的安全态势,并保护它免受未经授权访问和恶意活动影响。

## 高级主题

以下是关于 Amazon EKS cluster 创建高级主题的问题。本节测试你对 EKS cluster 创建中的高级概念和最佳实践的理解。

  1. 以下哪一项不是在 Amazon EKS cluster 中配置 IPv6 支持的要求?
    • A) 分配了 IPv6 CIDR block 的 VPC
    • B) 支持 IPv6 的 CNI plugin 版本
    • C) Dual-stack subnets
    • D) IPv6-only instance types
显示答案

答案:D) IPv6-only instance types

解释: “IPv6-only instance types”不是在 Amazon EKS cluster 中配置 IPv6 支持的要求。IPv6 支持不需要特殊 instance types,因为大多数 EC2 instance types 都支持 IPv6。实际要求是分配了 IPv6 CIDR block 的 VPC、支持 IPv6 的 CNI plugin 版本,以及 dual-stack subnets。

EKS 中 IPv6 支持的实际要求:

  1. 分配了 IPv6 CIDR block 的 VPC:

    • 必须向你的 VPC 分配 IPv6 CIDR block。
    • 可以通过 AWS Management Console 或 AWS CLI 配置。
    bash
    # Assign IPv6 CIDR block to existing VPC
    aws ec2 associate-vpc-cidr-block \
      --vpc-id vpc-12345 \
      --amazon-provided-ipv6-cidr-block
  2. 支持 IPv6 的 CNI plugin 版本:

    • 需要 Amazon VPC CNI plugin 版本 1.10.0 或更高版本。
    • 需要进行 IPv6 支持配置。
    bash
    # Check CNI version
    kubectl describe daemonset aws-node --namespace kube-system | grep Image
    
    # Update CNI
    kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/v1.10.0/config/master/aws-k8s-cni.yaml
    
    # Enable IPv6
    kubectl set env daemonset aws-node -n kube-system ENABLE_IPV6=true
  3. Dual-stack subnets:

    • Subnets 必须同时分配 IPv4 和 IPv6 CIDR blocks。
    • 必须在 route table 中配置 IPv6 routing。
    bash
    # Assign IPv6 CIDR block to subnet
    aws ec2 associate-subnet-cidr-block \
      --subnet-id subnet-12345 \
      --ipv6-cidr-block 2600:1f16:d93:e900::/64
    
    # Create IPv6 internet gateway
    aws ec2 create-egress-only-internet-gateway --vpc-id vpc-12345

创建 EKS IPv6 Cluster:

bash
# Create IPv6 cluster using eksctl
cat > ipv6-cluster.yaml << EOF
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: ipv6-cluster
  region: us-west-2
  version: '1.23'
vpc:
  id: vpc-12345
  subnets:
    private:
      us-west-2a:
        id: subnet-12345
      us-west-2b:
        id: subnet-67890
  clusterEndpoints:
    publicAccess: true
    privateAccess: true
kubernetesNetworkConfig:
  ipFamily: IPv6
managedNodeGroups:
  - name: ng-1
    instanceType: m5.large
    desiredCapacity: 2
EOF

eksctl create cluster -f ipv6-cluster.yaml

验证 IPv6 Cluster 配置:

bash
# Check cluster information
aws eks describe-cluster --name ipv6-cluster --query "cluster.kubernetesNetworkConfig"

# Verify Pod IP assignment
kubectl get pods -o wide

# Verify Service IP assignment
kubectl get services -o wide

IPv6 Clusters 的特征:

  1. Pod IP 分配:
    • Pods 仅分配 IPv6 addresses。
    • cluster 内部通信通过 IPv6 进行。
  2. Service IP 分配:
    • ClusterIP services 使用 IPv6 addresses。
    • 默认 service CIDR 是 fd00::/108。
  3. DNS 配置:
    • CoreDNS 配置为使用 IPv6 addresses。
    • 可通过 AAAA records 进行 service name resolution。
  4. 外部通信:
    • Internet 通信需要 Egress-Only Internet Gateway。
    • 入站通信需要启用 IPv6 的 load balancer。

使用 IPv6 的优势:

  1. 解决 IP Address Exhaustion:
    • 克服 IPv4 address space 的限制。
    • 解决大规模 clusters 中的 IP address shortage 问题。
  2. 简化 Networking:
    • 无需 NAT,简化 network 配置。
    • Direct routing 可以提升 network performance。
  3. 未来兼容性:
    • 为向 IPv6-only environments 过渡做准备。
    • 支持利用新的 networking features 和 optimizations。

“IPv6-only instance types”是一个不存在的概念,大多数 EC2 instance types 都支持 IPv6。在 EKS 中配置 IPv6 不需要选择特殊 instance types。

2. 配置 Amazon EKS cluster 中 custom networking 的主要好处是什么? - A) 将 Pod IP address range 与 VPC CIDR 分离以防止 IP address conflicts - B) 缩短 cluster 创建时间 - C) 提高 control plane 性能 - D) 加密 node-to-node 通信

显示答案

答案:A) 将 Pod IP address range 与 VPC CIDR 分离以防止 IP address conflicts

解释: 在 Amazon EKS cluster 中配置 custom networking 的主要好处,是将 Pod IP address range 与 VPC CIDR 分离,以防止 IP address conflicts。此功能便于与现有 network infrastructure 集成,并在大规模 clusters 中实现更高效的 IP address management。

Custom Networking 的工作方式:

默认情况下,Amazon VPC CNI plugin 从 node 的主 network interface 分配 secondary IP addresses,为 Pods 提供 IP addresses。在这种方法中,Pod IP addresses 从 VPC CIDR range 内分配。相比之下,custom networking 允许你从与 VPC CIDR 分离的 CIDR block 中分配 Pod IP addresses。

配置 Custom Networking 的步骤:

  1. 启用 Custom Networking:

    bash
    # Modify CNI plugin configuration
    kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true
  2. 创建 ENIConfig Resources:

    yaml
    # Create ENIConfig for each availability zone
    apiVersion: crd.k8s.amazonaws.com/v1alpha1
    kind: ENIConfig
    metadata:
      name: us-west-2a
    spec:
      subnet: subnet-12345
      securityGroups:
      - sg-12345
    ---
    apiVersion: crd.k8s.amazonaws.com/v1alpha1
    kind: ENIConfig
    metadata:
      name: us-west-2b
    spec:
      subnet: subnet-67890
      securityGroups:
      - sg-12345
  3. 启用基于 Availability Zone 的 ENIConfig 使用方式:

    bash
    kubectl set env daemonset aws-node -n kube-system ENI_CONFIG_LABEL_DEF=topology.kubernetes.io/zone
  4. 验证 Node Labels:

    bash
    kubectl get nodes --show-labels | grep topology.kubernetes.io/zone

Custom Networking 的优势:

  1. 防止 IP Address Conflicts:
    • 将 Pod IP address range 与 VPC CIDR 分离,以防止 IP address conflicts。
    • 便于与现有 network infrastructure 集成。
    • 对 on-premises networks 与 VPCs 之间的 peering 或 VPN connections 很有用。
  2. IP Address Management 的灵活性:
    • 允许单独规划和管理 Pod IP address ranges。
    • 在大规模 clusters 中实现更高效的 IP address management。
  3. Network Segmentation:
    • 通过将 Pods 放置在特定 subnets 中实现 network segmentation。
    • 可通过 security groups 进行 network access control。
  4. Multi-CIDR Support:
    • 可使用多个 CIDR blocks 扩展 IP address space。
    • 即使现有 VPC CIDR 有限,也可以构建大规模 clusters。

Custom Networking 的使用场景:

  1. Hybrid Network Environments:
    • 当 on-premises networks 与 AWS VPC 之间存在连接时
    • 当必须防止 IP address space 重叠时
  2. 大规模 Clusters:
    • 当运行大量 Pods 时
    • 当 VPC CIDR range 有限时
  3. 多租户环境:
    • 当每个 tenant 都需要单独 subnets 时
    • 当需要 network isolation 时
  4. 监管要求:
    • 当法规要求将特定 workloads 放置在特定 subnets 中时

其他选项的问题:

  • 缩短 cluster 创建时间: Custom networking 不会影响 cluster 创建时间,并且由于额外配置,实际上可能增加设置时间。
  • 提高 control plane 性能: Custom networking 只影响 data plane(worker nodes 和 Pods)networking,不会直接影响 control plane 性能。
  • 加密 node-to-node 通信: Custom networking 只改变 IP addresses 的分配方式,与 node-to-node 通信加密无关。Node-to-node 通信加密必须通过单独的安全机制实现(例如 Calico、Cilium encryption features)。

Custom networking 是一项强大功能,可以更灵活地配置 EKS cluster networking,但其配置复杂,并可能带来额外的管理开销,因此只有在确实需要时才应使用。

3. 以下哪一项不是在 Amazon EKS cluster 中支持 Windows worker nodes 的要求? - A) 需要至少 2 个基于 Amazon Linux 的 managed node groups - B) 安装 VPC-CNI、kube-proxy、CoreDNS add-ons - C) Windows Server 2019 或更高版本 AMI - D) Cluster 版本 1.14 或更高

显示答案

答案:A) 需要至少 2 个基于 Amazon Linux 的 managed node groups

解释: 要在 Amazon EKS cluster 中支持 Windows worker nodes,需要至少 1 个(不是 2 个或更多)基于 Amazon Linux 的 managed node group。这是因为 CoreDNS 等关键 system Pods 必须运行在 Linux nodes 上。但是,要求至少 2 个 Linux node groups 是不正确的。

EKS 中 Windows Worker Node 支持的实际要求:

  1. 需要 Linux Node Group:

    • cluster 中至少需要 1 个 Linux node。
    • CoreDNS、VPC CNI plugin 和 kube-proxy 等 System Pods 只在 Linux nodes 上运行。
    bash
    # Create Linux node group
    eksctl create nodegroup \
      --cluster my-cluster \
      --name linux-ng \
      --node-type m5.large \
      --nodes 2
  2. 安装 VPC-CNI、kube-proxy、CoreDNS Add-ons:

    • 这些 add-ons 是 EKS cluster 的关键组件。
    • Windows node 支持可能需要特定版本或更高版本。
    bash
    # Check add-on versions
    aws eks describe-addon-versions \
      --addon-name vpc-cni \
      --kubernetes-version 1.23
    
    # Update add-on
    aws eks update-addon \
      --cluster-name my-cluster \
      --addon-name vpc-cni \
      --addon-version v1.10.4-eksbuild.1
  3. Windows Server 2019 或更高版本 AMI:

    • Windows worker nodes 必须使用 Windows Server 2019 或更高版本 AMI。
    • 建议使用 EKS-optimized Windows AMI。
    bash
    # Create Windows node group
    eksctl create nodegroup \
      --cluster my-cluster \
      --name windows-ng \
      --node-type m5.large \
      --nodes 2 \
      --node-ami-family WindowsServer2019FullContainer
  4. Cluster 版本 1.14 或更高:

    • Windows node 支持从 Kubernetes 1.14 开始正式支持。
    • 建议使用更高版本以获得最新功能。
    bash
    # Check cluster version
    aws eks describe-cluster --name my-cluster --query "cluster.version"

启用 Windows 支持的步骤:

  1. 启用 Windows 支持:

    bash
    # Enable Windows support
    kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-resource-controller.yaml
    
    kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-admission-webhook.yaml
  2. 创建 Windows Node Group:

    bash
    # Create Windows node group using eksctl
    eksctl create nodegroup \
      --cluster my-cluster \
      --name windows-ng \
      --node-type m5.large \
      --nodes 2 \
      --node-ami-family WindowsServer2019FullContainer
  3. 验证 Windows Nodes:

    bash
    # Verify nodes
    kubectl get nodes -o wide
    
    # Verify Windows node labels
    kubectl get nodes -l kubernetes.io/os=windows

Windows Container Deployment 示例:

yaml
# Windows Pod deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: windows-server-iis
spec:
  selector:
    matchLabels:
      app: windows-server-iis
      tier: backend
      track: stable
  replicas: 2
  template:
    metadata:
      labels:
        app: windows-server-iis
        tier: backend
        track: stable
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: windows-server-iis
        image: mcr.microsoft.com/windows/servercore:ltsc2019
        ports:
        - containerPort: 80
        command:
        - powershell.exe
        - -command
        - "Add-WindowsFeature Web-Server; Invoke-WebRequest -UseBasicParsing -Uri 'https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe' -OutFile 'C:\\ServiceMonitor.exe'; echo '<html><body><br/><br/><center><h1>Hello from Windows Container</h1></center></body></html>' > C:\\inetpub\\wwwroot\\default.html; C:\\ServiceMonitor.exe 'w3svc';"

Windows Node 限制:

  1. Networking 限制:
    • Windows nodes 不支持 HostPort 和 HostNetwork 模式。
    • Windows nodes 不支持 NodeLocal DNSCache。
  2. Storage 限制:
    • Windows nodes 仅支持某些 storage drivers。
    • host path volume mounts 存在限制。
  3. Container Runtime:
    • Windows nodes 仅支持 containerd runtime。
    • Linux containers 不能在 Windows nodes 上运行。
  4. 功能限制:
    • 某些 Kubernetes features 在 Windows nodes 上不受支持。
    • privileged containers、process namespace sharing 等存在限制。

要在 EKS 中支持 Windows worker nodes,至少需要一个 Linux node group,但不强制要求两个或更多 Linux node groups。因此,“需要至少 2 个基于 Amazon Linux 的 managed node groups”不是准确的要求。

3. 以下哪一项不是在 Amazon EKS cluster 中支持 Windows worker nodes 的要求? - A) 需要至少 2 个基于 Amazon Linux 的 managed node groups - B) 安装 VPC-CNI、kube-proxy、CoreDNS add-ons - C) 使用 Windows Server 2019 或更高版本 AMI - D) Cluster 版本 1.14 或更高

显示答案

答案:A) 需要至少 2 个基于 Amazon Linux 的 managed node groups

解释: 要在 Amazon EKS cluster 中支持 Windows worker nodes,需要至少一个(不是两个或更多)基于 Amazon Linux 的 managed node group。这是因为 CoreDNS 等关键 system pods 必须运行在 Linux nodes 上。但是,要求至少两个 Linux node groups 并不准确。

EKS 中 Windows Worker Node 支持的实际要求:

  1. 需要 Linux Node Group:

    • cluster 至少需要一个 Linux node。
    • CoreDNS、VPC CNI plugin 和 kube-proxy 等 system pods 只在 Linux nodes 上运行。
    bash
    # Create Linux node group
    eksctl create nodegroup \
      --cluster my-cluster \
      --name linux-ng \
      --node-type m5.large \
      --nodes 2
  2. 安装 VPC-CNI、kube-proxy、CoreDNS Add-ons:

    • 这些 add-ons 是 EKS cluster 的基础组件。
    • Windows node 支持可能需要特定版本或更高版本。
    bash
    # Check add-on versions
    aws eks describe-addon-versions \
      --addon-name vpc-cni \
      --kubernetes-version 1.23
    
    # Update add-on
    aws eks update-addon \
      --cluster-name my-cluster \
      --addon-name vpc-cni \
      --addon-version v1.10.4-eksbuild.1
  3. 使用 Windows Server 2019 或更高版本 AMI:

    • Windows worker nodes 必须使用 Windows Server 2019 或更高版本 AMI。
    • 建议使用 EKS-optimized Windows AMI。
    bash
    # Create Windows node group
    eksctl create nodegroup \
      --cluster my-cluster \
      --name windows-ng \
      --node-type m5.large \
      --nodes 2 \
      --node-ami-family WindowsServer2019FullContainer
  4. Cluster 版本 1.14 或更高:

    • Windows node 支持从 Kubernetes 1.14 开始 generally available。
    • 建议使用更高版本以获得最新功能。
    bash
    # Check cluster version
    aws eks describe-cluster --name my-cluster --query "cluster.version"

启用 Windows 支持的步骤:

  1. 启用 Windows 支持:

    bash
    # Enable Windows support
    kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-resource-controller.yaml
    
    kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/master/vpc-admission-webhook.yaml
  2. 创建 Windows Node Group:

    bash
    # Create Windows node group using eksctl
    eksctl create nodegroup \
      --cluster my-cluster \
      --name windows-ng \
      --node-type m5.large \
      --nodes 2 \
      --node-ami-family WindowsServer2019FullContainer
  3. 验证 Windows Nodes:

    bash
    # Verify nodes
    kubectl get nodes -o wide
    
    # Verify Windows node labels
    kubectl get nodes -l kubernetes.io/os=windows

Windows Container Deployment 示例:

yaml
# Windows Pod deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: windows-server-iis
spec:
  selector:
    matchLabels:
      app: windows-server-iis
      tier: backend
      track: stable
  replicas: 2
  template:
    metadata:
      labels:
        app: windows-server-iis
        tier: backend
        track: stable
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: windows-server-iis
        image: mcr.microsoft.com/windows/servercore:ltsc2019
        ports:
        - containerPort: 80
        command:
        - powershell.exe
        - -command
        - "Add-WindowsFeature Web-Server; Invoke-WebRequest -UseBasicParsing -Uri 'https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe' -OutFile 'C:\\ServiceMonitor.exe'; echo '<html><body><br/><br/><center><h1>Hello from Windows Container</h1></center></body></html>' > C:\\inetpub\\wwwroot\\default.html; C:\\ServiceMonitor.exe 'w3svc';"

Windows Node 限制:

  1. Networking 限制:
    • Windows nodes 不支持 HostPort 和 HostNetwork 模式。
    • Windows nodes 不支持 NodeLocal DNSCache。
  2. Storage 限制:
    • Windows nodes 仅支持某些 storage drivers。
    • host path volume mounts 存在限制。
  3. Container Runtime:
    • Windows nodes 仅支持 containerd runtime。
    • Linux containers 不能在 Windows nodes 上运行。
  4. 功能限制:
    • 某些 Kubernetes features 在 Windows nodes 上不受支持。
    • privileged containers、process namespace sharing 等存在限制。

要在 EKS 中支持 Windows worker nodes,至少需要一个 Linux node group,但不强制要求两个或更多 Linux node groups。因此,“需要至少 2 个基于 Amazon Linux 的 managed node groups”不是准确的要求。

  1. 保护 Amazon EKS cluster 中 node groups 的 Instance Metadata Service (IMDS) 的最有效方式是什么?
    • A) 禁用 IMDSv1 并要求使用 IMDSv2
    • B) 使用 security group rules 限制对 169.254.169.254 的访问
    • C) 对 node IAM role 设置限制性权限
    • D) 将 IAM roles 附加到 pod service accounts
显示答案

答案:A) 禁用 IMDSv1 并要求使用 IMDSv2

解释: 保护 Amazon EKS cluster 中 node groups 的 Instance Metadata Service (IMDS) 的最有效方式,是禁用 IMDSv1 并要求使用 IMDSv2。IMDSv2 使用基于 session 的 requests 提供增强安全功能,可防御 Server-Side Request Forgery (SSRF) 和类似漏洞。

IMDS 安全的重要性:

Instance Metadata Service 提供有关 EC2 instances 的重要信息,包括 IAM role credentials。未经授权访问此 service 可能导致 privilege escalation 和 security breaches。在 Kubernetes environments 中,由于 pods 可以访问 node 的 IMDS,安全风险会增加。

如何配置 IMDSv2:

  1. 使用 Launch Template 配置 IMDSv2:

    bash
    # Create launch template
    aws ec2 create-launch-template \
      --launch-template-name eks-imdsv2-template \
      --version-description "IMDSv2 required" \
      --launch-template-data '{
        "MetadataOptions": {
          "HttpTokens": "required",
          "HttpPutResponseHopLimit": 1,
          "HttpEndpoint": "enabled"
        }
      }'
    
    # Create node group using launch template
    eksctl create nodegroup \
      --cluster my-cluster \
      --name ng-imdsv2 \
      --node-type m5.large \
      --nodes 3 \
      --launch-template-name eks-imdsv2-template \
      --launch-template-version 1
  2. 使用 eksctl 配置文件配置 IMDSv2:

    yaml
    apiVersion: eksctl.io/v1alpha5
    kind: ClusterConfig
    metadata:
      name: my-cluster
      region: us-west-2
    managedNodeGroups:
      - name: ng-imdsv2
        instanceType: m5.large
        minSize: 2
        maxSize: 5
        disableIMDSv1: true
        metadataOptions:
          httpTokens: required
          httpPutResponseHopLimit: 1
  3. 修改现有 Node Groups: 要更改现有 node groups 的 IMDS 设置,需要创建新的 node group 并迁移 workloads。现有 EC2 instances 的 IMDS 设置可以按如下方式修改:

    bash
    aws ec2 modify-instance-metadata-options \
      --instance-id i-1234567890abcdef0 \
      --http-tokens required \
      --http-put-response-hop-limit 1 \
      --http-endpoint enabled

IMDSv2 的安全优势:

  1. 基于 Session 的身份验证:
    • IMDSv2 使用通过 PUT requests 生成的 tokens 来验证后续 requests。
    • 这些 tokens 仅在有限时间内有效。
  2. SSRF 攻击防护:
    • 防止通过 Server-Side Request Forgery (SSRF) 漏洞访问 metadata。
    • 没有 token 就无法访问 metadata。
  3. Hop Limit 设置:
    • 设置 HTTP PUT response hop limit 可防止 metadata requests 被重定向到 instance 外部。
    • 默认值为 1,确保 requests 只在 instance 内部处理。

其他 IMDS 安全措施:

  1. 完全禁用 IMDS: 如果某些 workloads 不需要 IMDS,可以完全禁用它:

    yaml
    metadataOptions:
      httpEndpoint: disabled
  2. 阻止 Pod 访问 IMDS: 如果 pods 未使用 host networking,可以添加 iptables rules 阻止 IMDS 访问:

    bash
    iptables -t nat -A PREROUTING -d 169.254.169.254/32 -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:1
  3. 使用 IRSA: 使用 IAM Roles for Service Accounts (IRSA) 为 pods 提供所需 AWS 权限,并消除对 node IMDS 的依赖。

其他选项的问题:

  • 使用 security group rules 限制对 169.254.169.254 的访问: Security groups 控制来自 instance 外部的 traffic,但 IMDS 从 instance 内部访问,因此无法使用 security groups 限制。
  • 对 node IAM role 设置限制性权限: 这是良好的安全实践,但不会强化 IMDS 本身的安全。如果攻击者可以访问 IMDS,即使权限有限也可能被利用。
  • 将 IAM roles 附加到 pod service accounts: IRSA 是确保 pods 不依赖 node IMDS 的好方法,但它不会直接强化 node IMDS 本身的安全。

禁用 IMDSv1 并要求使用 IMDSv2 是保护 EKS nodes metadata service 的最有效方式。这是 AWS 安全最佳实践,在多租户 Kubernetes environments 中尤其重要。

  1. 以下哪一项不是在 Amazon EKS cluster 中创建 node groups 时自定义 bootstrap scripts 的主要目的?
    • A) 修改 cluster control plane components
    • B) 安装额外软件
    • C) 调整 kernel parameters
    • D) 设置 node labels 和 taints
显示答案

答案:A) 修改 cluster control plane components

解释: 在 Amazon EKS cluster 中创建 node groups 时,自定义 bootstrap scripts 的主要目的不是修改 cluster control plane components。EKS 是 managed service,control plane 由 AWS 管理,用户无法直接修改。Bootstrap scripts 只能修改 worker node configurations。

Bootstrap Scripts 的实际使用场景:

  1. 安装额外软件:

    • Monitoring agents (CloudWatch Agent, Prometheus Node Exporter 等)
    • Logging tools (Fluentd, Fluent Bit 等)
    • Security tools (Falco, Sysdig 等)
    • Performance optimization tools
    bash
    #!/bin/bash
    # Install CloudWatch agent
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
    rpm -U amazon-cloudwatch-agent.rpm
    
    # Create configuration file
    cat > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json << 'EOF'
    {
      "metrics": {
        "metrics_collected": {
          "mem": {
            "measurement": ["mem_used_percent"]
          },
          "swap": {
            "measurement": ["swap_used_percent"]
          }
        }
      }
    }
    EOF
    
    # Start agent
    /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s
  2. 调整 Kernel Parameters:

    • Network setting optimization
    • Memory management settings
    • File system 和 I/O settings
    bash
    #!/bin/bash
    # Adjust kernel parameters
    cat > /etc/sysctl.d/99-kubernetes.conf << EOF
    net.ipv4.ip_forward = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.ipv4.tcp_keepalive_time = 600
    net.ipv4.tcp_max_syn_backlog = 40000
    net.core.somaxconn = 40000
    net.core.netdev_max_backlog = 40000
    vm.max_map_count = 262144
    EOF
    
    # Apply changes
    sysctl --system
  3. 设置 Node Labels 和 Taints:

    • 设置 node role labels
    • 设置 hardware characteristic labels
    • 为特定 workloads 设置 taints
    bash
    #!/bin/bash
    # Execute EKS bootstrap script
    /etc/eks/bootstrap.sh my-cluster \
      --kubelet-extra-args '--node-labels=node.kubernetes.io/role=worker,environment=prod,node-type=compute --register-with-taints=dedicated=compute:NoSchedule'
  4. Disk 和 File System 配置:

    • 挂载额外 volumes
    • File system optimization
    • Temporary storage configuration
    bash
    #!/bin/bash
    # Format and mount additional EBS volume
    mkfs -t xfs /dev/nvme1n1
    mkdir -p /data
    mount /dev/nvme1n1 /data
    echo "/dev/nvme1n1 /data xfs defaults 0 0" >> /etc/fstab
  5. 安全配置:

    • 设置 firewall rules
    • Security hardening settings
    • Log audit configuration
    bash
    #!/bin/bash
    # Set firewall rules
    iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT
    iptables -A INPUT -p tcp --dport 22 -j DROP
    
    # Security hardening settings
    sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
    systemctl restart sshd

如何实现 Bootstrap Scripts:

  1. 使用 Launch Template 的 User Data Script:

    bash
    # Create launch template
    aws ec2 create-launch-template \
      --launch-template-name eks-custom-bootstrap \
      --version-description "Custom bootstrap script" \
      --launch-template-data '{
        "UserData": "BASE64_ENCODED_USER_DATA_SCRIPT"
      }'
    
    # Create node group using launch template
    eksctl create nodegroup \
      --cluster my-cluster \
      --name custom-ng \
      --node-type m5.large \
      --nodes 3 \
      --launch-template-name eks-custom-bootstrap \
      --launch-template-version 1
  2. 使用 eksctl 配置文件的 User Data Script:

    yaml
    apiVersion: eksctl.io/v1alpha5
    kind: ClusterConfig
    metadata:
      name: my-cluster
      region: us-west-2
    managedNodeGroups:
      - name: custom-ng
        instanceType: m5.large
        minSize: 2
        maxSize: 5
        preBootstrapCommands:
          - "echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.d/99-kubernetes.conf"
          - "sysctl --system"
        kubeletExtraArgs:
          node-labels: "environment=prod,node-type=compute"

Cluster Control Plane Components:

EKS cluster 的 control plane components 由 AWS 管理,不能通过 bootstrap scripts 修改:

  • API Server
  • Controller Manager
  • Scheduler
  • etcd
  • CoreDNS

要修改这些 components,必须通过 AWS 提供的 APIs 在 cluster 级别进行配置。例如,control plane logging 可以按如下方式配置:

bash
aws eks update-cluster-config \
  --name my-cluster \
  --logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'

Bootstrap script 只能修改 worker node configurations,不能修改 cluster control plane components。因此,“修改 cluster control plane components”不是 bootstrap script 的主要目的。