参考官网说明文档:https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kubelet/

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

[root@master01 ssl]# kubectl logs nginx-deployment-6b474476c4-gdbdn

Error from server: Get https://172.31.3.205:10250/containerLogs/default/nginx-deployment-6b474476c4-gdbdn/nginx: dial tcp 172.31.3.205:10250: connect: connection refused

【备注:节点处于联机状态并且可以运行pod,但是从kube-apiserver到节点的连接失败,并显示“ x509:未知授权机构签名的证书”。】

 

网上搜索可以通过启用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、手工指定证书

     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的。

 

      7、验证授权kubelet客户端证书:

[root@node001 ssl]# openssl verify -CAfile /etc/kubernetes/ssl/ca.pem kubelet-client.crt

kubelet-client.crt: OK

表示验证OK!

 

 

2、自签名证书和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步只是生成服务端证书。

 

5、查看自动生成kubelet 客户端证书:

此时如果要验证这个证书那么肯定是失败报错的如下:

[root@node001 ssl]# openssl verify -CAfile /opt/kubernetes/ssl/ca.pem kubelet.crt

kubelet.crt: CN = 172.31.3.205@1611981969

error 20 at 0 depth lookup:unable to get local issuer certificate

【提示:未知授权机构签名的证书!】

备注:如果是客户端自动生成的证书那么apiserver 配置文件中不能有参数:kubelet-certificate-authority 否则就报本文一开始错误!

 

 

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角色,这是最高的权限,可以根据需要创建低权限角色。

[root@master01 ssl]# 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,客户端证书需要手工配置。

 

Logo

开源、云原生的融合云平台

更多推荐