深入理解kubelet认证和授权

在通过kubectl访问pod信息,例如执行kubectl logs,常常会遇到类似如下错误:

Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log tiller-deploy-6b5ffb6f-lg9jb)

网上搜索可以通过启用anonymous访问,也就是使用--anonymous-auth=true或者配置文件添加:

authentication:
    anonymous:
        enabled: true

但是设置之后错误依旧,为此我探究了一下kubelet的认证机制,终于将问题解决,其实很简单,答案后面揭晓。

我们知道kubectl只会和apiserver交互,对于kubectl logs、kubectl exec等需要访问pod的这些命令,实际上是apiserver调用kubelet接口完成的,上述错误正是出在这个过程,而不是kubectl到apiserver的过程。

kubelet通过port指定的端口(默认10250)对外暴露服务,这个服务是需要TLS认证的,同时也可以通过 readOnlyPort 端口(默认10255,0表示关闭)对外暴露只读服务,这个服务是不需要认证的。apiserver通过--kubelet-https参数指定调用哪个服务,true为前者,false为后者,此时只能执行只读操作。下面主要说一下前者。

认证过程

配置认证方式

有三种可配置认证方式:

  1. TLS认证,这也是默认的

    authentication:
        anonymous:
            enabled: false
        webhook:
         enabled: false
        x509:
         clientCAFile: xxxx
    
  2. 允许anonymous,这时可不配置客户端证书

    authentication:
        anonymous:
            enabled: true
    
  3. webhook,这时可不配置客户端证书

    authentication:
        webhook:
         enabled: true
    

    这时kubelet通过bearer tokens,找apiserver认证,如果存在对应的serviceaccount,则认证通过。

如果2开启,则忽略x509和webhook认证;否则,如果1和3同时开启,则按1、3的顺序依次认证,任何一个认证通过则返回通过,否则认证不通过。

通过kubectl命令行访问kubelet时,无法传递bearer tokens,所以无法使用webhook认证,这时只能使用x509认证。

证书配置

kubelet对外暴露https服务,必须设置服务端证书,如果通过x509证书认证客户端,那么还需要配置客户端证书。下面说明证书配置的三种方法:

手工指定证书

  1. 假设ca的证书和key:ca.pem,ca-key.pem

  2. 用上述ca生成kubelet服务端证书和key:kubelet-server.pem、kubelet-server-key.pem

  3. 用上述ca生成apiserver使用的客户端证书和key:kubelet-client.pem、kubelet-client-key.pem,证书CN为kubelet-client

  4. 修改kubelet的配置文件:

    tlsCertFile: kubelet-server.pem
    tlsPrivateKeyFile: kubelet-server-key.pem
    authentication:
        x509:
            clientCAFile: ca.pem
    
  5. 修改apiserver参数:

    --kubelet-certificate-authority=ca.pem --kubelet-client-certificate=kubelet-client.pem --kubelet-client-key=kubelet-client-key.pem
    
  6. 授权kubelet-client用户:

    kubectl create clusterrolebinding kubelet-admin --clusterrole=system:kubelet-api-admin --user=kubelet-client
    

    经过上面5步,认证的过程实际已经OK了,第6步是为授权过程服务的,kubelet的授权是通过webhook委托给apiserver的。

自签名证书和key

实际上是上述过程的特化,不指定tlsCertFile和tlsPrivateKeyFile时,kubelet会自动生成服务端证书保存在--cert-dir指定目录中,文件名为kubelet.crt和kubelet.key,这个证书是自签名的,所以apiserver不需要指定--kubelet-certificate-authority,其他配置是一样的。

通过TLS bootstrap机制

还可以通过TLS bootstrap机制分配kubelet服务证书。跟配置分配访问apiserver的客户端证书方法是一样的(参考官方文档),额外的配置如下:

  1. 修改kubelet配置文件:

    serverTLSBootstrap: true 
    
  2. 授权允许创建kubelet服务端证书

    首先创建system:certificates.k8s.io:certificatesigningrequests:selfnodeserver,默认是没有创建的。

    selfnodeserver.yaml文件如下:

    # A ClusterRole which instructs the CSR approver to approve a node requesting a
    # serving cert matching its client cert.
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
    rules:
    - apiGroups: ["certificates.k8s.io"]
      resources: ["certificatesigningrequests/selfnodeserver"]
      verbs: ["create"]
    
    kubectl create -f selfnodeserver.yaml
    

    然后创建绑定:

    kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeserver --group=system:nodes
    
  3. 手工批准证书请求:

    先查询证书请求:

    [vagrant@localhost etc]$ kubectl get csr
    NAME                                                   AGE     REQUESTOR                 CONDITION
    csr-2jxvn                                              76s     system:node:10.10.10.16   Pending
    

    然后批准证书:

    kubectl certificate approve csr-2jxvn
    

    之后在相应kubelet的--cert-dir目录可以看到服务端证书已经生成。

  4. 配置客户端证书和前面的方法是一样的,上面3步只是生成服务端证书。

选择哪种方式

客户端证书配置是免不了的,区别是在服务端证书,显然自动生成更加方便,TLS bootstrap相对于自签名证书更加安全,集群统一使用信任的CA签名。

TLS bootstrap还可以配置证书过期后自动重新生成,方法是修改kubelet配置文件:

rotateCertificates: true 

TLS bootstrap分配证书的有效期可以通过kube-controller-manager如下参数修改,默认8760h0m0s,也就是1年:

--experimental-cluster-signing-duration

授权过程

配置授权方式

可配置两种授权方式:

  1. AlwaysAllow:从字面意思就可知道

    authorization:
     mode: AlwaysAllow
    
  2. Webhook:这是默认模式

    authorization:
     mode: Webhook
    

    这时授权过程是委托给apiserver的,使用apiserver一样的授权模式,也就是RBAC。

配置权限

如果通过Webhook授权,就需要通过RBAC为用户配置权限。

首先要弄清楚通过认证的用户是什么,通过x509证书认证的用户名是客户端证书中的CN字段,用户组为O字段;通过webhook认证的用户是token对应的serviceaccount;没有通过认证或使能anonymous,则用户为system:anonymous。

其次要弄清楚应该授权什么权限,系统已经存在一个system:kubelet-api-admin角色,这是最高的权限,可以根据需要创建低权限角色。

[vagrant@localhost kube-apiserver]$ kubectl describe clusterrole system:kubelet-api-admin
Name:         system:kubelet-api-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources      Non-Resource URLs  Resource Names  Verbs
  ---------      -----------------  --------------  -----
  nodes/log      []                 []              [*]
  nodes/metrics  []                 []              [*]
  nodes/proxy    []                 []              [*]
  nodes/spec     []                 []              [*]
  nodes/stats    []                 []              [*]
  nodes          []                 []              [get list watch proxy]

最后将用户和角色绑定,即完成权限的配置。

总结

如何配置kubelet的认证和授权,归结起来常用如下2种做法:

  1. 省事型,可用于开发环境

    authentication:
        anonymous:
            enabled: true
    authorization:
     mode: AlwaysAllow        
    

    一开始出现的Forbidden问题就是没有配置AlwaysAllow,默认是Webhook。

  2. 安全型,生产环境使用

    authentication:
        anonymous:
            enabled: false
    authorization:
     mode: Webhook
    

    服务端证书通过TLS bootstrap,客户端证书需要手工配置。

欢迎访问钟潘的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容