zoukankan      html  css  js  c++  java
  • Kubernetes 中的 Pod 安全策略

    来源:伪架构师

    作者:崔秀龙

    很多人分不清 SecurityContext 和 PodSecurityPolicy 这两个关键字的差别,其实很简单:

    •SecurityContext 是 Pod 中的一个字段,而 PSP 是一个独立的资源类型。

    •SecurityContext 是 Pod 自身对安全上下文的声明;

    而 PSP 则是强制实施的——不合规矩的 Pod 无法创建。

    PSP 的用法和 RBAC 是紧密相关的,换句话说,应用 PSP 的基础要求是:

    •不同运维人员的操作账号需要互相隔离并进行单独授权。

    •不同命名空间,不同 ServiceAccount 也同样要纳入管理流程。

    PSP 环境下,运维人员或者新应用要接入集群,除了 RBAC 设置之外,还需要声明其工作范围所需的安全策略,并进行绑定,才能完成工作。

    PSP 的官方文档中提到,PSP 是通过 Admission Controller 启用的,并且注明了:启用 PSP 是一个有风险的工作,未经合理授权,可能导致 Pod 无法创建。

    开始之前,首先设置一个别名,在 default 命名空间新建 ServiceAccount 来模拟一个有权创建 Pod 的用户:

    $ kubectl create sa common
    serviceaccount/common created
    
    $ kubectl create rolebinding common --clusterrole=edit --serviceaccount=default:common
    rolebinding.rbac.authorization.k8s.io/common created
    
    $ alias kube-common='kubectl --as=system:serviceaccount:default:common'
    



    第一个 PSP

    我们首先创建一个不允许创建特权 Pod 的策略:

    apiVersion: policy/v1beta1
    kind: PodSecurityPolicy
    metadata:
    name: noprivileged
    spec:
    privileged: false
    seLinux:
    rule: RunAsAny
    supplementalGroups:
    rule: RunAsAny
    runAsUser:
    rule: RunAsAny
    fsGroup:
    rule: RunAsAny
    volumes:
    - '*'
    



    保存为 psp.noprivileged.yaml 并提交给集群。

    接下来创建两个 Pod:

    apiVersion: v1
    kind: Pod
    metadata:
    name: noprivileged
    spec:
    containers:
    - name: pause

    image: k8s.gcr.io/pause

    apiVersion: v1
    kind: Pod
    metadata:
    name: privileged
    spec:
    containers:
    - name: pause
    image: k8s.gcr.io/pause
    securityContext:
      privileged: true
    



    用普通用户创建这个 Pod:

    $ kube-common apply -f pod.yaml && kube-common delete -f pod.yaml
    pod/noprivileged created
    pod/privileged created
    pod "noprivileged" deleted
    pod "privileged" deleted
    



    可以看到,在不允许创建特权容器的规则之中,我们的用户还是能够创建特权容器,这是因为还没启用 PSP,接下来在集群设置中启动 PSP,各种环境的启用方式不同,例如在 GKE 环境:

    $ gcloud beta container clusters update gcp-k8s --enable-pod-security-policy --zone=asia-east1-a
    Updating gcp-vlab-k8s...done.
    



    删除重建 Pod:

    $ kube-common apply -f pod.yaml && kube-common delete -f pod.yaml
    Error from server (Forbidden): error when creating "pod.yaml": pods "noprivileged" is forbidden: unable to validate against any pod security policy: []
    Error from server (Forbidden): error when creating "pod.yaml": pods "privileged" is forbidden: unable to validate against any pod security policy: []
    



    可以看到,Pod 的新建请求被拒绝了——然而使用集群管理员身份还是能成功创建的:

    $ kubectl apply -f pod.yaml && kubectl delete -f pod.yaml
    pod/noprivileged created
    pod/privileged created
    pod "noprivileged" deleted
    pod "privileged" deleted
    



    全员 admin 是万恶之源。

    用 RBAC 进行授权:

    $ kubectl create role psp:noprivileged 
    --verb=use 
    --resource=podsecuritypolicy 
    --resource-name=noprivileged
    role.rbac.authorization.k8s.io/psp:noprivileged created
    
    $ kubectl create rolebinding common:psp:noprivileged 
    --role=psp:noprivileged 
    --serviceaccount=default:common
    rolebinding.rbac.authorization.k8s.io/common:psp:noprivileged created
    



    再试试普通用户的能力:

    $ kube-common apply -f pod.yaml ; kube-common delete -f pod.yaml
    pod/noprivileged created
    Error from server (Forbidden): error when creating "pod.yaml": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
    pod "noprivileged" deleted
    Error from server (NotFound): error when deleting "pod.yaml": pods "privileged" not found
    



    非特权 Pod 才能够成功创建,这符合我们的预期。

    副作用

    Pod 成功创建了之后,顺理成章,做个 Deployment 看看:

    kind: Deployment
    metadata:
    name: privileged
    spec:
    replicas: 1
    template:
    metadata:
      labels:
        app: pause
        version: v1
    spec:
      containers:
      - name: sleep
        image: k8s.gcr.io/pause
        securityContext:

    privileged: true

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
    name: noprivileged
    spec:
    replicas: 1
    template:
    serviceAccount: common
    metadata:
      labels:
        app: pause
        version: v1
    spec:
      containers:
      - name: sleep
        image: k8s.gcr.io/pause
    



    我们会发现,Deployment 无法正常工作:

    $ kubectl get pods
    kuNo resources found in default namespace.
    $ kubectl get deployment
    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    noprivileged   0/1     0            0           15m
    privileged     0/1     0            0           15m
    



    查看一下事件:

    $ kubectl get events | grep policy
    8m38s       Warning   FailedCreate        replicaset/noprivileged-6f94f9c9b8                 Error creating: pods "noprivileged-6f94f9c9b8-" is forbidden: unable to validate against any pod security policy: []
    8m38s       Warning   FailedCreate        replicaset/privileged-6d78d5458                    Error creating: pods "privileged-6d78d5458-" is forbidden: unable to validate against any pod security policy: []
    



    这次的 Pod 不是由我们授权的 common 用户创建的,而是由 RS Controller 启动的,因此会失败,加入一个 Service Account:

    ...
    spec:
      serviceAccount: common
      containers:
    ...
    spec:
      serviceAccount: common
      containers:
    ...
    



    提交变更,会发现非特权 Pod 开始创建:

    $ kubectl get pods
    NAME                            READY   STATUS    RESTARTS   AGE
    noprivileged-6cf595c5bd-rc8cx   1/1     Running   0          4s
    



    系统 Pod 怎么办

    这时候我想到个问题,其它 Pod 会不会受到影响?我删除了 kube-system 下面的一个 kube-proxy的 Pod,发现这个 Pod 自动重建了,没有受到 PSP 的影响,查看一下 RBAC 相关配置,会发现 GCP 在更新集群的过程中已经为系统服务进行了预设:

    $ kubectl get rolebinding
    ...
    gce:podsecuritypolicy:kube-proxy                    80m
    gce:podsecuritypolicy:metadata-agent                80m
    gce:podsecuritypolicy:metadata-proxy                80m
    gce:podsecuritypolicy:nodes                         80m
    ...
    



    追查下去:

    $ kubectl get rolebinding gce:podsecuritypolicy:metadata-proxy -o yaml
    ...
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: gce:podsecuritypolicy:privileged
    subjects:
    - kind: ServiceAccount
    name: metadata-proxy
    namespace: kube-system
    



    如果追查其中涉及到的 ClusterRole,会发现它指向一个 PSP:

    $ kubectl get clusterrole gce:podsecuritypolicy:privileged -o yaml
    ...
    rules:
    - apiGroups:
    - policy
    resourceNames:
    - gce.privileged
    resources:
    - podsecuritypolicies
    verbs:
    - use
    



    看看这个 PSP 的内容:

    $ kubectl get psp  gce.privileged -o yaml
    ...
    privileged: true
    ...
    



    的确包含了特权 Pod 的内容。

    最后看看负责创建这个特权 Pod 的 Daemonset:

    $  kubectl get daemonset  metadata-proxy-v0.1 -o yaml
    ...
      serviceAccount: metadata-proxy
      serviceAccountName: metadata-proxy
    ...
    



    PSP的限制能力

    分为以下几个大方面:

    •特权容器

    •主机命名空间:

    例如 HostPID、HostNetwork 等。

    •卷和文件系统:

    例如 PVC、configMap、emptyDir 等卷类型,以及 fsGroup、AllowedHostPaths 等加载能力。

    •用户和组:

    运行身份

    •提权:

    是否允许

    •Capability 和 sysctl

    •SeLinux、AppArmor 等。

    马后炮

    kubectl 的 advise-psp 插件,能够根据当前运行的 Pod,提取出所需的 PSP 信息。

    参考链接:

    https://kubernetes.io/docs/con ... licy/

  • 相关阅读:
    win10 UWP button
    内网分享资源
    内网分享资源
    CF724F Uniformly Branched Trees
    win10 UWP FlipView
    win10 UWP FlipView
    win10 UWP FlipView
    搭建阿里云 centos mysql tomcat jdk
    搭建阿里云 centos mysql tomcat jdk
    win10 UWP 申请微软开发者
  • 原文地址:https://www.cnblogs.com/alauda/p/12867743.html
Copyright © 2011-2022 走看看