kubernetes 认证及 serviceaccount

整个 k8s 集群的 APIserver 是访问控制的唯一入口,但不会限制应用程序,任何用户试图操作资源对象时,要经历三个环节

  • 认证: 访问 k8s 的账号和安全认证
  • 授权: 是否有操作资源对象的权限
  • 准入控制: 级联的其他资源是否有权限

用户可以通过多种插件来选择通过何种逻辑方式完成认证和准入控制如: token、SSL 等,其中 SSL 认证客户端需要验证服务端的 CA 证书同时,服务端也要认证 kubectl 的 CA 证书.如果环境中存在多个认证插件则不会串行认证,授权来说也可以通过插件来完成用户的授权间检查,k8s 1.6 之后开始支持基于 RBAC 认证,此前支持诸如 ABAC 的认证等,RBAC 与 LINUX 权限认证相思,默认拒绝所有请求只允许某些权限,所以可以细致到普通用户的各种独立权限.准入控制逻辑本身只是用来定义授权检查通过后的其他权限

同时也需要注意 k8s 集群上的证书一般是自签证书,任何这个自签机构颁发的证书都可以被 k8s 完成认证

用户账号权限

API server 识别用户的权限通过以下几种协议来识别

  • 用户账号 user:username,uid
  • 用户组 group:用户所属的组,权限指派和继承
  • 附加权限 extra: 键值数据的字符串,用于提供认证时需要提供额外信息

更重要的是用户会请求具体某个特定的 API 资源,而 k8s 的 API server 是分组的,则用户会通过在 HTTP 协议当中的 URL 来标识的,如 http://${MasterIP}:6443/apis/apps/v1/namespaces/default/deployments/myapp-deploy /apis/<GROUP>/<VERSION>/namespace/<NAMESPACE_NAME>/<KIND>[/OBJECT_ID]/

[root@master-0 ~]# kubectl proxy --port=8080
Starting to serve on 127.0.0.1:8080
[root@master-0 ~]# curl http://localhost:8080/api/v1/namespaces
... ...

与 API server 打交道的有两种身份

  • 集群外部: 每次访问 apiserver 时,都是请求其所在的节点进行访问
  • 集群内部: apiserver 有一个名为 kubernetes 的 svc,作为给集群内部 pod 访问的 ip 地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1JrBNGfM-1624627871200)(https://raw.githubusercontent.com/ma823956028/image/master/picgo/20200914103824.png)]

[root@master-0 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.208.0.1       <none>        443/TCP   165d
myapp        ClusterIP   10.208.208.208   <none>        80/TCP    12d
myapp-svc    ClusterIP   None             <none>        80/TCP    97d
[root@master-0 ~]# kubectl describe svc kubernetes
Name:              kubernetes
Namespace:         default
Labels:            component=apiserver
                provider=kubernetes
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.208.0.1
Port:              https  443/TCP
TargetPort:        6443/TCP
Endpoints:         10.211.55.35:6443
Session Affinity:  None
Events:            <none>

由于这种特殊的集群内部 apiserver 的机制,做证书时需要指明 apiserver 本身 ip 和 kubernetes svc 的 ip,同时由于双向认证的关系,容器内的服务如果要访问 apiserver 也需要进行认证,这个认证是 pod 的 spec.serviceAccountName 提供的

[root@master-0 ~]# kubectl explain pod.spec.serviceAccountName
KIND:     Pod
VERSION:  v1

FIELD:    serviceAccountName <string>

DESCRIPTION:
    ServiceAccountName is the name of the ServiceAccount to use to run this
    pod. More info:
    https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

而各个 pod 多少都会与 apiserver 交互,所以每个名称空间下都会有一个和 apiserver 交互时的 token,但默认这个 token 只能管理 pod 自身

[root@master-0 ~]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-lbf5s   kubernetes.io/service-account-token   3      165d
[root@master-0 ~]# kubectl get secret -ningress-nginx
NAME                                  TYPE                                  DATA   AGE
default-token-hfbph                   kubernetes.io/service-account-token   3      12d

serviceAccount

  1. 创建的 serviceAccount 只是账号,后需要通过 RBAC 来赋予真正的权限

    [root@master-0 ~]# kubectl create serviceaccount mysa -o yaml --dry-run         # dry-run 可以输出框架,同时对于运行的 pod 也可以使用 --export 来导出 yaml 文件
    W0912 01:25:59.806447   11484 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client.
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      creationTimestamp: null
      name: mysa
    [root@master-0 ~]# kubectl get sa
    NAME      SECRETS   AGE
    default   1         165d
    [root@master-0 ~]# kubectl create serviceaccount admin
    serviceaccount/admin created
    [root@master-0 ~]# kubectl describe sa admin
    Name:                admin
    Namespace:           default
    Labels:              <none>
    Annotations:         <none>
    Image pull secrets:  <none>                 # pod 拉取镜像时连接私有仓库的认证信息,比 secret 安全
    Mountable secrets:   admin-token-zr6cw
    Tokens:              admin-token-zr6cw
    Events:              <none>
    [root@master-0 ~]# kubectl get secret
    NAME                  TYPE                                  DATA   AGE
    admin-token-zr6cw     kubernetes.io/service-account-token   3      16s
    ... ...
    
  2. 让 pod 挂载使用这个 sa

[root@master-0 ~]# cat pod-sa-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: nginx
    ports:
    - name: http
      containerPort: 80
    imagePullPolicy: IfNotPresent
  serviceAccountName: admin
[root@master-0 ~]# kubectl apply -f pod-sa-demo.yaml
pod/pod-sa-demo created

认证信息的配置文件

  1. 除了 apiserver 自己本身,其他所有组件几乎都需要与其进行认证,而每个组件的认证信息配置文件被称为 kubeconfig,显示 kubeconfig 设置命令为 kubectl config view

    [root@master-0 ~]# kubectl config view
    apiVersion: v1
    clusters:                                           # 集群列表
    - cluster:
        certificate-authority-data: DATA+OMITTED        # 服务器认证这个集群的认证方式,私密数据
        server: https://10.211.55.35:6443               # 访问集群的 apiserver 路径
      name: kubernetes
    contexts:
    - context:                                          # 上下文列表,这个配置文件不单单可以访问一个 k8s 集群,context 则注明哪个账号可以访问那个集群
        cluster: kubernetes                             # 集群名
        user: kubernetes-admin                          # 访问这个集群用的用户信息
      name: kubernetes-admin@kubernetes                 # context 的名字
    current-context: kubernetes-admin@kubernetes        # 当前上下文
    kind: Config
    preferences: {}
    users:                                               # 用户列表
    - name: kubernetes-admin
      user:
        client-certificate-data: REDACTED               # 被集群认证的信息
        client-key-data: REDACTED
    
  2. 在配置文件中增加新的账号信息

    [root@master-0 ~]# cd /etc/kubernetes/
    [root@master-0 kubernetes]# cd pki/
    [root@master-0 pki]# ls
    apiserver.crt              apiserver.key                 ca.crt  front-proxy-ca.crt      front-proxy-client.key
    apiserver-etcd-client.crt  apiserver-kubelet-client.crt  ca.key  front-proxy-ca.key      sa.key
    apiserver-etcd-client.key  apiserver-kubelet-client.key  etcd    front-proxy-client.crt  sa.pub
    [root@master-0 pki]# (umask 077 ; openssl genrsa -out test.key 2048)    # 生成私钥
    Generating RSA private key, 2048 bit long modulus
    .......................................................................................................+++
    ...+++
    e is 65537 (0x10001)
    [root@master-0 pki]# openssl req -new -key test.key -out test.cr -subj "/CN=test"       # CN 就是用户账号的名字
    [root@master-0 pki]# openssl x509 -req -in test.cr -CA ca.crt -CAkey ca.key -CAcreateserial -out test.crt -days 365     # 签署证书
    Signature ok
    subject=/CN=test
    Getting CA Private Key
    [root@master-0 pki]# openssl x509 -in test.crt -text -noout
    Certificate:
        Data:
            Version: 1 (0x0)
            Serial Number: 17177463334185398281 (0xee629be4706af009)
        Signature Algorithm: sha1WithRSAEncryption
            Issuer: CN=kubernetes
            Validity
                Not Before: Sep 12 06:28:32 2020 GMT
                Not After : Sep 12 06:28:32 2021 GMT
            Subject: CN=test
            ... ...
    [root@master-0 pki]# kubectl config set-credentials
    Usage:
    kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--client-key=path/to/keyfile]
    [--token=bearer_token] [--username=basic_user] [--password=basic_password] [--auth-provider=provider_name]
    [--auth-provider-arg=key=value] [--exec-command=exec_command] [--exec-api-version=exec_api_version] [--exec-arg=arg]
    [--exec-env=key=value] [options]
    [root@master-0 pki]# kubectl config set-credentials testadmin  --client-certificate=./test.crt --client-key=./test.key  --embed-certs=true
    User "testadmin" set.
    [root@master-0 pki]# kubectl config set-context --help
    Usage:
    kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--user=user_nickname]
    [--namespace=namespace] [options]
    [root@master-0 pki]# kubectl config set-context testadmin@kubernetes --cluster=kubernetes --user=test
    Context "testadmin@kubernetes" created.
    [root@master-0 pki]# kubectl config view
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: DATA+OMITTED
        server: https://10.211.55.35:6443
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: kubernetes-admin
      name: kubernetes-admin@kubernetes
    - context:
        cluster: kubernetes
        user: test
      name: testadmin@kubernetes
    current-context: kubernetes-admin@kubernetes
    kind: Config
    preferences: {}
    users:
    - name: kubernetes-admin
      user:
        client-certificate-data: REDACTED
        client-key-data: REDACTED
    - name: testadmin
      user:
        client-certificate-data: REDACTED
        client-key-data: REDACTED
    [root@master-0 pki]# kubectl config use-context testadmin@kubernetes
    Switched to context "testadmin@kubernetes".
    [root@master-0 pki]# kubectl config use-context kubernetes-admin@kubernetes
    

准入控制

一般不会手动操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值