2023年6月27日发(作者:)
深⼊理解k8s中的访问控制(认证、鉴权、审计)流程Kubernetes⾃⾝并没有⽤户管理能⼒,⽆法像操作Pod⼀样,通过API的⽅式创建/删除⼀个⽤户实例,也⽆法在etcd中找到⽤户对应的存储对象。在Kubernetes的访问控制流程中,⽤户模型是通过请求⽅的访问控制凭证(如kubectl使⽤的kube-config中的证书、Pod中引⼊的ServerAccount)产⽣的Kubernetes API的请求从发起到其持久化⼊库的流程如图:
⼀、认证阶段(Authentication)判断⽤户是否为能够访问集群的合法⽤户。apiserver⽬前提供了9种认证机制。每⼀种认证机制被实例化后会成为认证器(Authenticator),每⼀个认证器都被封装在r请求处理函数中,它们接收组件或客户端的请求并认证请求。
假设所有的认证器都被启⽤,当客户端发送请求到kube-apiserver服务,该请求会进⼊Authentication Handler函数(处理认证相关的Handler函数)。在Authentication Handler函数中,会遍历已启⽤的认证器列表,尝试执⾏每个认证器,当有⼀个认证器返回true时,则认证成功,否则继续尝试下⼀个认证器;如果⽤户是个⾮法⽤户,那apiserver会返回⼀个401的状态码,并终⽌该请求。1、RequestHeader认证Kubernetes可以设置⼀个认证代理,客户端发送的认证请求可以通过认证代理将验证信息发送给apiserverapiserver需要配置: --requestheader-username-headers=X-Remote-User --requestheader-group-headers=X-Remote-Group --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-client-ca-file:防⽌头部欺骗 --requestheader-allowed-names:设置允许的CN列表
2、BasicAuth认证启动apiserver时通过--basic-auth-file参数启⽤BasicAuth认证。AUTH_FILE(Static Password file)是⼀个CSV⽂件,⽂件格式为:password,user,uid,"group1,group2,group3"发起请求时在HTTP中添加头即可:Authorization: Basic BASE64ENCODED(USER:PASSWORD)
3、clientCA认证X509认证是Kubernetes组件间默认使⽤的认证⽅式,同时也是kubectl客户端对应的kube-config中经常使⽤到的访问凭证。它是⼀个⽐较安全的⽅式。⾸先访问者会使⽤由集群CA签发的,或是添加在apiserver配置中的授信CA签发的客户端证书去访问apiserver。apiserver在接收到请求后,会进⾏TLS的握⼿流程。除了验证证书的合法性,apiserver还会校验客户端证书的请求源地址等信息,开启双向认证。
进⾏证书签发的步骤:(1)创建根CAcat << EOF | tee { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } }}EOF其中:profiles:指定不同的过期时间、使⽤场景等参数。⽂件中可以定义多个,分别后续在签名证书时使⽤某⼀个signing:表⽰该证书可⽤于签名其它证书,⽣成的证书中CA=TRUEkey encipherment:表⽰密钥⽤法为密钥加密server auth:表⽰client可以⽤该CA 对server提供的证书进⾏验证client auth:表⽰server可以⽤该CA对client提供的证书进⾏验证cat << EOF | tee { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Shenzhen", "ST": "Shenzhen", "O": "k8s", "OU": "System" } ]}EOF其中:CN:Common Name,⽤于从中提取该字段作为请求的⽤户名C:Country, 国家ST: State,州,省L: Locality,地区,城市O: Organization Name, ⽤于从中提前该字段作为请求⽤户所属的组OU: Organization Unit Name,组织单位名称,公司部门cfssl gencert -initca | cfssljson -bare ca执⾏后⽣成⽂件、、(2)签发其它系统组件的证书Kubernetes集群中所有系统组件与apiserver通讯⽤到的证书,其实都是由集群根CA来签发的。①如kube-proxy对应的csr⽂件cat << EOF | tee { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Shenzhen", "ST": "Shenzhen", "O": "k8s", "OU": "System" } ]}EOF使⽤根CA签署证书:cfssl gencert -ca= -ca-key= -config= -profile=kubernetes | cfssljson -bare kube-proxy执⾏后⽣成⽂件、、②kubelet启动时实际需要指定两个配置⽂件 --kubeconfig指定的是kube-config⽂件,其中内置了集群根CA公钥以及⾃⼰作为客户端的公钥和私钥 --config指定的是kubelet的配置,格式如下:kind: KubeletConfigurationapiVersion: /v1beta1address: t: 10250readOnlyPort: 10255cgroupDriver: cgroupfsclusterDNS: ["10.0.0.2"]clusterDomain: apOn: falseauthentication: anonymous: enabled: truekubelet组件在⼯作时,采⽤主动的查询机制,即定期请求apiserver 获取⾃⼰所应当处理的任务,如哪些pod分配到了⾃⼰⾝上,从⽽去处理这些任务;同时kubelet⾃⼰还会暴露出两个本⾝api的端⼝,⽤于将⾃⼰本⾝的私有api暴露出去,这两个端⼝分别是该配置⽂件中指定的10250与10255。对于10250端⼝,kubelet会在其上采⽤TLS加密以提供适当的鉴权功能;对于10255端⼝,kubelet会以只读形式暴露组件本⾝的私有api,并且不做鉴权处理。因此,kubelet上实际上有两个地⽅⽤到证书,⼀个是⽤于与 API server通讯所⽤到的证书,另⼀个是该配置⽂件中设置的kubelet的10250私有api端⼝需要⽤到的证书。(3)签发⽤户的证书①⾸先开发⼈员需⽤通过OpenSSL等证书⼯具⽣成私钥openssl genrsa -out 2048②创建对应的x509 csr请求⽂件(需要在subj字段中指定user和group)openssl req -new -key -out -subj "/CN=xxxx/O=xxxx"③Kubernetes集群本⾝就提供了证书签发的API /v1beta1。调⽤后,api-server会根据请求,以csr资源对象的形式创建对应的签发请求。例如,在集群的创建过程中,像kubeadm这样的集群安装⼯具,也会基于不同的csr签发请求调⽤api-server对应接⼝,创建不同的csr资源对象。⽤户可以通过API创建K8s csr实例并等待管理员审批。cat < "clusters": [ { "cluster": { "certificate-authority": "server": "ip:6443" }, "name": {cluster-name} } ], "contexts": [ { "context": { "cluster": {cluster-name}, "user": {user-name} }, "name": {context-name} } ], "users": [ { "name": {user-name}, "user": { "client-certificate": "client-key": } } ] "current-context": {context-name},}若想要⽤base64编码数据代替认证⽂件,需要添加后缀-data,将 certificate-authority、client-certificate、client-key改为certificate-authority-data、client-certificate-data、client-key-data从config⽂件还原证书的⽅法:# grep 'client-key-data' /etc/kubernetes/ | head -n 1 | awk '{print $2}' | base64 -d # grep 'client-certificate-data' /etc/kubernetes/ | head -n 1 | awk '{print $2}' | base64 -d⑤下载集群ca公钥⽂件,使⽤kubectl添加集群连接信息# kubectl config set-cluster xxx --certificate-authority= --embed-certs=true --server=ip:6443⑥使⽤kubectl设置kubeconfig的users配置段信息,需要将⽤户秘钥信息加⼊kubectl配置中# kubectl config set-credentials {user-name} --client-certificate= --client-key= --embed-certs=true⑦添加新的context⼊⼝到kubectl配置中# kubectl config set-context {context-name} --cluster={cluster-name} --user={user-name}⑧多集群config的合并和切换# export KUBECONFIG=file1:file2:file3 # kubectl config view --merge --flatten > ~/.kube/all-config # export KUBECONFIG = ~/.kube/all-config⑨查看和切换上下⽂# kubectl config get-contests # kubectl config use-context {your-contexts} 4、TokenAuth认证启动apiserver时通过--token-auth-file参数启⽤TokenAuth认证。AUTH_FILE(Static Password file)是⼀个CSV⽂件,⽂件格式为:token,user,uid,"group1,group2,group3"发起请求时在HTTP中添加头即可:Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269 5、ServiceAccountAuth认证serviceaccount是k8s中唯⼀能够通过API⽅式管理的apiserver访问凭证,通常⽤于pod中的业务进程与apiserver的交互ServiceAccount解决Pod在集群⾥⾯的⾝份认证问题,认证使⽤的授权信息存在secret⾥⾯(由SecretAccount Controller⾃⾏创建)。当⼀个namespace创建完成后,会同时在该namespace下⽣成名为default的serviceaccount和对应Secret:apiVersion: v1kind: ServiceAccountmetadata: creationTimestamp: "2019-11-19T03:07:32Z" name: default namespace: default resourceVersion: "191" selfLink: /api/v1/namespaces/default/serviceaccounts/default uid: b2322727-08d5-4095-acbe-1afee4fb5e6csecrets:- name: default-token-nfdr4 对应的Secret⾥: data字段有两块数据:⽤于对服务端的校验,token⽤于Pod的⾝份认证,它们都是⽤base64编码过的。 metadata⾥annotations字段表明了关联的ServiceAccount信息(被哪个ServiceAccount使⽤)。 type字段表明了该Secret是service-account-token类型apiVersion: v1data: : namespace: ZGVmYXVsdA== token: kind: Secretmetadata: annotations: /: default /: b2322727-08d5-4095-acbe-1afee4fb5e6c creationTimestamp: "2019-11-19T03:07:32Z" name: default-token-nfdr4 namespace: default resourceVersion: "190" selfLink: /api/v1/namespaces/default/secrets/default-token-nfdr4 uid: cbb919a4-6309-43c0-ac0b-566e30e9b116type: /service-account-token此外,⽤户也可以通过api创建其它名称的ServiceAccount,并在该namespace的Pod的.eAccount下指定,默认是default。Pod创建的时候,Admission Controller会根据指定的ServiceAccount把对应secret的和token⽂件挂载到固定⽬录/var/run/secrets//serviceaccount下。 volumeMounts: - mountPath: /var/run/secrets//serviceaccount name: default-token-jbcp7 readOnly: truepod要访问集群的时候,默认利⽤Secret其中的token⽂件来认证Pod的⾝份,利⽤校验服务端默认token的认证信息为: - Group:system:serviceaccounts:[namespace-name] - User:system:serviceaccount:[namespace-name]:defaultPod⾝份被认证合法后,其权限需要通过RBAC来配置,默认只有资源GET权限 PS:如果是在Pod创建过程中,发现指定的ServiceAccount不存在,则该Pod创建过程会被终⽌。PS:对于已经创建的Pod,不能更新其已经挂载的ServiceAccount内容。 6、Bootstrap Token认证如果节点多起来,为每个节点单独签署证书将是⼀件⾮常繁琐的事情TLS bootstrapping的功能就是让kubelet先使⽤⼀个预定的低权限⽤户连接到apiserver,向apiserver申请证书,证书由apiserver动态签署在配合RBAC授权模型下的⼯作流程⼤致如下所⽰:TLS bootstrapping下kubelet发起的CSR请求⼤致分为以下三种: nodeclient:kubelet以O=system:nodes、CN=system:node:(node name)形式发起的CSR请求(仅在第⼀次启动时产⽣) selfnodeclient:kubelet发起的更新⾃⼰的作为client的证书的CSR请求(与上⼀个证书有相同的O、CN) selfnodeserver:kubelet发起的更新⾃⼰的作为server的证书(即kubelet 10250 api端⼝证书)的CSR请求 ①使⽤TLS Bootstrapping Token时的配置流程:(1)创建TLS Bootstrapping Token# head -c 16 /dev/urandom | od -An -t x | tr -d ' '8f01b7072246e0f3409d54e379c8699f(2)修改⽤户的描述⽂件(相当于预设的⽤户配置),基本格式为Token,user,uid,group:8f01b7072246e0f3409d54e379c8699f,kubelet-bootstrap,10001,"system:kubelet-bootstrap"(3)在apiserver配置中添加--enable-bootstrap-token-auth开启TLS bootstrapping功能,通过--token-auth-file参数指定⽂件,apiserver启动时会将其加载,相当于在集群内创建了这个⽤户。(4)kubelet-bootstrap⽤户没有任何权限(包括创建CSR请求),需要创建⼀个ClusterRoleBinding,将预设⽤户kubelet-bootstrap⽤户与内置的ClusterRole system:node-bootstrapper绑定到⼀起,使其能够发起 CSR 请求# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap否则kubelet会报401⽆权访问apiserver的错误(4)创建kubelet的配置⽂件nfigBOOTSTRAP_TOKEN=01f6717d648e3e7e71282a9632dd99abKUBE_APISERVER="132.224.197.35:6443"执⾏命令:# kubectl config set-cluster kubernetes --certificate-authority=./ --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=nfig # kubectl config set-credentials kubelet-bootstrap --token=${BOOTSTRAP_TOKEN} --kubeconfig=nfig # kubectl config set-context default --cluster=kubernetes --user=kubelet-bootstrap --kubeconfig=nfig # kubectl config use-context default --kubeconfig=nfigkubelet-bootstrap⽤户的Token和apiserver的使⽤的CA证书被写⼊了该配置⽂件中⾸次请求时,kubelet使⽤配置⽂件中的apiserver CA证书与apiserver建⽴TLS通讯,使⽤配置⽂件中的⽤户Token向apiserver声明⾃⼰的RBAC授权⾝份。(5)启动kubelet时需要指定--kubeconfig和--bootstrap-kubeconfig(两种⾝份),指定--cert-dir⽤来存放所有证书(6)在kubelet⾸次启动后,如果⽤户Token没问题,并且RBAC也做了相应的设置,那么此时在集群内应该能看到kubelet发起的CSR 请求。出现CSR请求后,可以使⽤kubectl⼿动签发kubelet的证书(7)当成功签发证书后,⽬标节点的 kubelet 会将证书写⼊到--cert-dir选项指定的⽬录中 、:kubelet与apiserver通讯所使⽤的证书 、:⽤于kubelet的10250端⼝做鉴权使⽤(这个证书是个独⽴于apiserver CA的⾃签CA,并且删除后kubelet会重新⽣成它) 配置controller manager⾃动签署证书kubelet发起的CSR请求都是由controller manager来做实际签署的(1)kubelet启动时增加--feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true参数,则证书即将到期时会⾃动发起⼀个renew⾃⼰证书的CSR请求 配置了--feature-gates=RotateKubeletClientCertificate=true后,kubelet⾸次启动时仍会使⽤证书与apiserver通信。续期请求被批准后会⽣成⼀个kubelet-client-时间戳.pem,⽂件则始终软连接到最新的真实证书⽂件 配置了--feature-gates=RotateKubeletServerCertificate=true后不再⽣成,改为⽣成kubelet-server-时间戳.pem,⽂件则始终软连接到最新的真实证书⽂件(2)controller manager启动时增加--feature-gates=RotateKubeletServerCertificate=true参数,则会在kubelet发起证书请求的时候⾃动帮助其签署证书PS:如果不配置该参数,则即使配置了相关的RBAC规则,也只会⾃动批准kubelet client的更新证书请求此外,还需要配置RBAC 规则,保证 controller manager只对kubelet发起的特定CSR请求⾃动批准(3)针对kubelet发起的3种CSR请求创建3种对应的ClusterRole:# A ClusterRole which instructs the CSR approver to approve a user requesting node client :ClusterRoleapiVersion:/v1metadata:name:approve-node-client-csrrules:-apiGroups:[""]resources:["certificatesigningrequests/nodeclient"]verbs:["create"] --- # A ClusterRole which instructs the CSR approver to approve a node renewing its own client :ClusterRoleapiVersion:/v1metadata:name:approve-node-client-renewal-csrrules:-apiGroups:[""]resources:["certificatesigningrequests/selfnodeclient"]verbs:["create"] --- # A ClusterRole which instructs the CSR approver to approve a node requesting a serving cert matching its client :ClusterRoleapiVersion:/v1metadata:name:approve-node-server-renewal-csrrules:-apiGroups:[""]resources:["certificatesigningrequests/selfnodeserver"]verbs:["create"]PS:1.8后的apiserver⾃动创建了前两条ClusterRole(4)将适当的ClusterRole绑定到 kubelet ⾃动续期时所所采⽤的⽤户或者⽤户组⾝上⾃动批准kubelet的⾸次CSR请求(⽤于与apiserver通信的证书):# kubectl create clusterrolebinding node-client-auto-approve-csr --clusterrole=approve-node-client-csr --group=system:bootstrappers⾃动批准 kubelet 后续 renew ⽤于与 apiserver 通讯证书的 CSR 请求:# kubectl create clusterrolebinding node-client-auto-renew-crt --clusterrole=approve-node-client-renewal-csr --group=system:nodes⾃动批准 kubelet 发起的⽤于 10250 端⼝鉴权证书的 CSR 请求(包括后续 renew):# kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=approve-node-server-renewal-csr --group=system:nodesPS:在 1.8 后kubelet需要增加--rotate-certificates参数,kubelet 才会⾃动重载新证书PS:在 1.7 版本以后kube-controller-manager可以通过--experimental-cluster-signing-duration参数来设置签署的证书有效时间,默认为8760h0m0s(1年)。 ②使⽤TLS Bootstrapping Token Secret时的配置流程:(1)⽣成tokenecho "$(head -c 6 /dev/urandom | md5sum | head -c 6)"."$(head -c 16 /dev/urandom | md5sum | head -c 16)”47f392.d22d04e89a65eb22Token 必须满⾜ [a-z0-9]{6}.[a-z0-9]{16} 格式;以 . 分割,前⾯的部分被称作Token ID(可以暴露出去),后⾯的部分称为Token Secret(需要保密)(2)创建Bootstrap Token SecretapiVersion: v1kind: Secretmetadata: name: bootstrap-token-07401b namespace: kube-systemtype: /tokenstringData: description: "The default bootstrap token generated by 'kubeadm init'." token-id: 47f392 token-secret: d22d04e89a65eb22 expiration: 2018-09-10T00:00:11Z usage-bootstrap-authentication: "true" usage-bootstrap-signing: "true" auth-extra-groups: system:bootstrappers:worker,system:bootstrappers:ingresstype 必须为 /tokenname 必须为 bootstrap-token- usage-bootstrap-authentication、usage-bootstrap-signing 必须设置为 trueexpiration 字段是可选的,如果设置则到期后将由 Controller Manager 中的 tokencleaner ⾃动清理auth-extra-groups 也是可选的,令牌的扩展认证组,组必须以system:bootstrappers:开头 (3)引导时,kubelet使⽤Token发起的请求其⽤户名为system:bootstrap: # kubectl config set-credentials system:bootstrap:47f392 --token=47f392.d22d04e89a65eb22 --kubeconfig=nfig # kubectl config set-context default --cluster=kubernetes --user=system:bootstrap:47f392 --kubeconfig=nfig # kubectl config use-context default --kubeconfig=nfig 7、OIDC认证所谓OIDC(OpenID Connect),就是先向identity provider获取服务器签名的JSON Web Token (JWT)identity provider会提供access_token、id_token、refresh_token使⽤kubectl时通过--token参数添加id_token,或者直接把它添加到kubeconfig⽂件中,kubectl会把id_token添加到http头⾥apiserver会通过证书确认JWT是否有效、确认JWT是否过期、⾝份是否合法等使⽤OIDC认证,apiserver需要配置: --oidc-issuer-url:identity provider的地址 --oidc-client-id:client id,⼀般配成kubernetes --oidc-username-claim,如sub --oidc-groups-claim,如groups --oidc-ca-file:为identity provider签名的CA公钥 8、Webhook TokenAuth认证当客户端发送的认证请求到达apiserver时,apiserver回调钩⼦⽅法,将验证信息发送给远程的Webhook服务器进⾏认证,然后根据Webhook服务器返回的状态码来判断是否认证成功通过指定如下参数启⽤WebhookTokenAuth认证: --authentication-token-webhook-config-file:Webhook配置⽂件描述了如何访问远程Webhook服务 --authentication-token-webhook-cache-ttl:缓存认证时间,默认值为2分钟 9、Anonymous认证未被其他认证器拒绝的请求都可视为匿名请求,匿名⽤户权值很低apiserver通过指定--anonymous-auth参数启⽤Anonymous认证,默认该参数值为true 认证流程之后,api-server会将请求中凭证中的⽤户⾝份转化为对应的User和Groups。在随后的鉴权操作和审计操作流程中,api-server都会使⽤该⽤户模型实例。⼆、鉴权阶段(Authorization)采⽤RBAC判断⽤户是否有权限进⾏请求中的操作。如果⽆权进⾏操作,api-server会返回403的状态码,并终⽌该操作RBAC包含三个要素:Subjects:可以是开发⼈员、集群管理员这样的⾃然⼈,也可以是系统组件进程、Pod中的业务进程;API Resource:也就是请求对应的访问⽬标,在Kubernetes集群中指各类资源对象;Verbs:对应为请求对象资源可以进⾏哪些操作,如list、get、watch等。部分常⽤操作需要的权限如下: Role:定义了⽤户在指定的Kubernetes namespace上可以进⾏哪些操作通过RoleBinding进⾏role和Subject的绑定:除了定义指定namespace中的权限模型,也可以通过ClusterRole定义⼀个集群维度的权限模型。以定义集群维度的权限(如PV、Nodes等namespace中不可见的资源)ClusterRole编排⽂件⼏乎和Role⼀样,删除指定namespace的那⾏即可。通过ClusterRoleBinding进⾏ClusterRole和Subject的绑定。 系统预置的ClusterRole: system:basic-user:system:unauthenticated组(未认证⽤户组)默认绑定Role,⽆任何操作权限 cluster-admin:system:masters组默认绑定的ClusterRole,有集群管理员权限 系统组件(kube-controller-manager、kube-scheduler、)都绑定了默认的ClusterRole 三、审计阶段(AdmissionControl)Admission Controller(准⼊控制器)是⼀个拦截器,被编译进API Server的可执⾏⽂件内部它以插件的形式运⾏在apiserver进程中,会在鉴权阶段之后、对象被持久化到etcd之前,拦截apiserver的请求,对请求的资源对象执⾏⾃定义(校验、修改或拒绝等)操作。AC有⼏⼗种,⼤体上分为3类: validating(验证型)⽤于验证k8s的资源定义是否符合规则 mutating(修改型)⽤于修改k8s的资源定义,如添加label,⼀般运⾏在validating之前 既是验证型⼜是修改型只要有⼀个准⼊控制器拒绝了该请求,则整个请求被拒绝(HTTP 403Forbidden)并返回⼀个错误给客户端。可通过--enable-admission-plugins参数指定启⽤的准⼊控制器列表,通过--disable-admission-plugins参数指定禁⽤的准⼊控制器列表查看打开的AC:# kube-apiserver -h | grep enable-admission-plugins --admission-control strings Admission is divided into two phases. In the first phase, only mutating admission plugins run. In the second phase, only valida --enable-admission-plugins strings admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, Service可见,AC⼀共有⼏⼗种,下⾯介绍⼀些常⽤的:1、ResourceQuota和LimitRangerResourceQuota可以限制namespace资源⽤量apiVersion: v1kind: ResourceQuotametadata: name: ns-quota-cns-test namespace: cns-testspec: hard: pods: "4" : "1" : 1Gi : "26" : 2Gi scopeSelector: matchExpressions: - operator: Exists scopeName: :除了基础的资源,还可以可以限制Pod数量elector:定义更丰富的索引能⼒,包括Terminating/Not Terminating、BestEffort/NotBestEffort、PriorityClass。创建ResourceQuota后,如果⽤户⽤超了资源,在提交Pod时,会收到⼀个forbidden的403错误,提⽰exceeded quota。但假如⽤户提交没有包含在这个ResourceQuota⽅案⾥⾯的资源,还是能成功的。 在某个namespace下创建LimitRange,则会⾃动为该namespace下的容器添加request和limit例如创建该LimitRange:apiVersion: v1 kind: LimitRange metadata: name: mem-limit-range spec: limits: - default: memory: 512Mi defaultRequest: memory: 256Mi type: Container会⾃动为所在命名空间下的容器添加256M的内存request和512M的内存limit 2、SecurityContextDenySecurityContext⽤于限制容器的⼀个⾏为,保证系统和其他容器的安全。从粒度上⼜分为以下两种: Container-level Security Context:仅应⽤到指定的容器 Pod-level Security Context:应⽤到Pod内所有容器以及Volume该能⼒不是Kubernetes或者容器runtime本⾝的能⼒,⽽是kubernetes和runtime通过⽤户的配置,最后下传到内核⾥,再通过内核的机制让其⽣效。Pod级别和容器级别配置SecurityContext的例⼦:apiVersion: v1kind: Podmetadata: name: security-context-demospec: securityContext: runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 volumes: - name: sec-ctx-vol emptyDir: {} containers: - name: sec-ctx-demo image: busybox command: [ "sh", "-c", "sleep 1h" ] volumeMounts: - name: sec-ctx-vol mountPath: /data/demo securityContext: allowPrivilegeEscalation: falseSecurityContext设置项主要包括:(1)通过⽤户ID和组ID来控制⽂件访问权限;(2)SELinux:通过策略配置来控制⽤户或者进程对⽂件的访问控制;(3)特权容器;(4)Capabilities:给特定进程来配置⼀个privileged能⼒;(5)AppArmor:通过⼀些配置⽂件来控制可执⾏⽂件的⼀个访问控制权限(⽐如说⼀些端⼝的读写);(6)对系统调⽤的控制;(7)对⼦进程能否获取⽐⽗亲更多的权限的⼀个限制最后其实都是落到内核来控制它的⼀些权限。 3、PodSecurityPolicyPod Security Policies(PSP)是应⽤到集群内部所有Pod以及Volume的安全策略PSP的使⽤:(1)通过在apiserver的admission-plugin参数中添加PodSecurityPolicy开启:(2)在集群中创建PSP策略实例,⽀持的控制项包括:(3)配置策略与⾝份的RBAC策略绑定(⼤多数pod中使⽤的⾝份都是Serviceaccount)(4)启动PSP后admission会强制要求pod在鉴权后找到⾄少⼀个对应的策略实例,因此最好设置⼀个集群维度的全局策略,同时针对指定namespace配置细化策略(5)如果同时有多个PSP满⾜权限绑定关系,优先从⾮mutating(不改变Pod模型的策略)的满⾜策略中按照实例name名字母排序选择第⼀个 4、ValidatingAdmissionWebhook和MutatingAdmissionWebhookwebhook就是⼀个HTTP回调,接收API Server发送的admissionReview请求,处理(验证或修改)并返回admissionResponse。使⽤步骤:(1)创建ValidatingWebhookConfiguration⽂件和MutatingWebhookConfiguration⽂件:apiVersion: /v1beta1kind: ValidatingWebhookConfigurationmetadata: name: validation-kube-webhook-cfg namespace: paas labels: app: paas-webhookwebhooks: - name: clientConfig: service: name: paas-webhook-svc namespace: paas path: "/validating" caBundle: rules: - operations: [ "CREATE" ] apiGroups: ["apps", "extensions", ""] apiVersions: ["v1", "v1beta1"] resources: ["services"] namespaceSelector: matchLabels: paas-webhook: enabled其中rules定义了匹配规则,当发给apiserver的请求满⾜该规则的时候,apiserver就会给clientConfig中配置的service发送Admission请求。(2)开发的webhook程序需要实现IWebHookServer接⼝:type IWebHookServer interface { mutating(ar *ionReview) *ionResponse validating(ar *ionReview) *ionResponse Start() Stop()}例如,定义⼀个结构体:type webHookServer struct { server *}实现这四个⽅法:①开始func (ws *webHookServer) Start() { AndServeTLS("", "")}②结束func (ws *webHookServer) Stop() { ("Got OS shutdown signal, shutting down wenhook ") wn(ound())}在main函数中调⽤go ()后,可以以如下⽅式阻塞,等待退出信号后再调⽤()signalChan := make(chan , 1)(signalChan, , M)<-signalChan ()③mutating负责修改④validating负责审核可以⽤⼀个req := t接下请求是ersionKind(GVK结构体)例如是Service时的反序列化:var service hal(, &service)resourceName, resourceNamespace, objectMeta = , ace, &Meta最后返回结果的数据结构:type AdmissionResponse struct { UID `json:"uid" protobuf:"bytes,1,opt,name=uid"` Allowed bool `json:"allowed" protobuf:"varint,2,opt,name=allowed"` Result * `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` Patch []byte `json:"patch,omitempty" protobuf:"bytes,4,opt,name=patch"` PatchType *PatchType `json:"patchType,omitempty" protobuf:"bytes,5,opt,name=patchType"` AuditAnnotations map[string]string `json:"auditAnnotations,omitempty" protobuf:"bytes,6,opt,name=auditAnnotations"`}返回⽰例:allowed := trueresult = &{ Reason: "Unauthorized nodeport",}return &ionResponse{ Allowed: allowed, Result: result,}webhook可以做到很多事情,例如限制每个namespace使⽤的端⼝号、为每个Pod插⼊sidecar容器等。 参考资料:[5] 郑东旭《Kubernetes源码剖析》
发布者:admin,转转请注明出处:http://www.yc00.com/news/1687803405a46422.html
评论列表(0条)