可以使用kubectl客户端库方式对REST API的访问,Kubernetes的普通账户和Service帐户都可以实现授权访问API。API的请求会经过多个阶段的访问控制才会被接受处理,

其中包含认证、授权以及准入控制(Admission Control)等。如下图所示:

kubernetes 的用户 kubernetes service account_kubernetes 的用户

需要注意:认证授权过程只存在HTTPS形式的API中。也就是说,如果客户端使用HTTP连接到kube-apiserver,是不会进行认证授权的。所以说,可以这么设置,在集群内部组件间通信使用HTTP

集群外部就使用HTTPS,这样既增加了安全性,也不至于太复杂。

认证

开启TLS时,所有的请求首先需要认证。Kubernetes支持多种认证机制,并支持同时开启多个认证插件(只要有一个认证通过即可)。如果认证成功,则用户的username会传入授权模块做进一步授权验证;对于认证失败的请求则返回HTTP 401。

当TLS建立时,HTTP请求会进行身份认证步骤,如图中步骤1,集群管理器将apiserver配置为运行一个或多个认证器模块。

认证模块包含客户端证书,密码、Plain Tokens、Bootstrap Tokens、JWT Tokens(used for service accounts)。

我们可以指定多个认证模块,每个认证模块都会按顺序进行,直到其中一个成功。

(在GCE上,客户端证书、密码、Plain Tokens和JWT Tokens都会启用。)

更多认证模块的使用方法可以参考 官方文档认证

所有Kubernetes集群有两类用户:由Kubernetes管理的Service Accounts (服务账户)和(Users Accounts) 普通账户。

普通账户是假定被外部或独立服务管理的,由管理员分配keys,用户像使用Keystone或google账号一样,被存储在包含usernames和passwords的list的文件里。

需要注意:在Kubernetes中不能通过API调用将普通用户添加到集群中

相比之下,Service Accounts是由Kubernetes API管理的帐户。它们被绑定到特定的命名空间,并由APIserver自动创建或通过API调用手动创建。Service Accounts与存储为Secrets的一组证书相关联,这些凭据被挂载到pod中,以便集群进程与Kubernetes API通信。

Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同

  • User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计;
  • User account是跨namespace的,而service account则是仅局限它所在的namespace;
  • 每个namespace都会自动创建一个default service account
  • Token controller检测service account的创建,并为它们创建secret
  • 开启ServiceAccount Admission Controller后
  • 每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)
  • 验证Pod引用的service account已经存在,否则拒绝创建
  • 如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中
  • 每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/

验证策略

Kubernetes用户可以使用client certificates、bearer tokens、authenticating proxy、HTTP basic auth等认证插件来验证API请求。比如HTTP请求到达API Server,插件会尝试将以下属性与请求关联:

  • UserName:普通用户的字符串。比如“kube-admin”或“xxxx@kubernetes.org.cn”。
  • UID:普通用户的字符串,比UserName更具有唯一性。
  • Groups:一组字符串,将常用的user分组的组合字符串。
  • Extra fields:将一些有用的字符串信息映射成的列表。

所有values值对于认证系统都是不透明的,只有当授权解释后才有意义。

可以同时启用多个认证方法。最少使用两种:

  • 为Service Accounts使用service account tokens方法。
  • 使用另外一种用户认证方法。

system:authenticated组被包括在所有已认证用户的组列表中。

详细的认证参考认证

开启本机的代理来访问API ,来获取相应的资源

[root]@k8s-master ~]# kubectl proxy --port=8080
Starting to serve on 127.0.0.1:8080

API group

下面命令可以看到API 有哪些组

[root@k8s-master k8s]# kubectl api-versions
curl http://localhost:8080/api/v1/namespaces/
[root@k8s-master ~]# kubectl get  deploy -n kube-system
curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/
    curl http://localhost:8080/apis/apps/v1/namespaces/kube-system/deployments/coredns

pod通过内部网络访问APIserver 

[root@k8s-master ~]# kubectl get svc
[root@k8s-master ~]# kubectl describe svc kubernetes
    Name:              kubernetes
    Namespace:         default
Labels:            component=apiserver
    IP:                10.96.0.1
    Port:              https  443/TCP

    [root@k8s-master ~]# kubectl explain pods.spec.serviceAccountName
kubectl describe pod myapp-deploy-675558bfc5-4f8hz
volumes:
    default-token-zzm2j:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-zzm2j
[root@k8s-master k8s]# kubectl get secret
    NAME                                          TYPE                                         DATA               AGE
default-token-zzm2j      kubernetes.io/service-account-token           3                    53d
    mysql-root-password                   Opaque                                         1                    10d
    tomcat-ingress-secre          t   kubernetes.io/tls                                   2                    11d
kubectl create  serviceaccount -h
[root@k8s-master k8s]# kubectl create  serviceaccount mysa -o yaml --dry-run(没生成,用来做测试,或者打印yaml)
apiVersion: v1
    kind: ServiceAccount
    metadata:
        creationTimestamp: null
        name: mysa    kubectl get pods myapp-deploy-675558bfc5-4f8hz -o yaml --export 导出相应的配置清单
[root@k8s-master k8s]# kubectl get sa(serviceaccount)
     NAME               SECRETS      AGE
     default                     1                53d

自己创建sa

[root@k8s-master k8s]# kubectl create sa admin
     serviceaccount/admin created
[root@k8s-master k8s]# kubectl get sa
     NAME         SECRETS   AGE
admin              1              6s
     default             1             53d
[root@k8s-master k8s]# kubectl describe sa admin
Mountable secrets:   admin-token-77fqm
      Tokens:              admin-token-77fqm [root@k8s-master k8s]# kubectl get secret
     NAME                                      TYPE                                                             DATA                AGE
admin-token-77fqm           kubernetes.io/service-account-token                        32                  6s
     default-token-zzm2j          kubernetes.io/service-account-token                         3                   53d


POD 中引入自己新建的sa,默认用的是default 
vim pod-sa.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-sa
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
  serviceAccountName: admin

kubectl describe pods pod-sa
admin-token-77fqm:
Type: Secret (a volume populated by a Secret)
SecretName: admin-token-77fqm
kubectl describe sa admin
Image pull secrets: <none>
如果用使用私有仓库,两种方式:
1.sa 定义这个Image pull secrets
2.定义POD 指定 Image pull secrets

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2015-08-07T22:02:39Z
  name: default
  namespace: default
  selfLink: /api/v1/namespaces/default/serviceaccounts/default
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey

 在K8S集群当中,每一个用户对资源的访问都是需要通过apiserver进行通信认证才能进行访问的,那么在此机制当中,对资源的访问可以是token

也可以是通过配置文件的方式进行保存和使用认证信息,可以通过kubectl config进行查看配置,如下:

kubeconfig 认证格式的客户端配置文件

[root@k8s-master k8s]# kubectl config view
apiVersion: v1
clusters: #集群列表
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.211.55.11:6443
  name: kubernetes 
contexts: #上下文列表
- context:用哪个账号访问哪个集群,可以是多个
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes  #当前使用的
kind: Config
preferences: {}
users: #用户列表
- name: kubernetes-admin 
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
kubectl config -h


各种证书生成到这个下面:
/etc/kubernetes/pki

创建自定义的签名证书

(umask077;openssl genrsa -out doudou.key 2048)
openssl req -new -key doudou.key -out doudou.csr -subj "/CN=doudou"
openssl x509 -req -in doudou.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial  -out doudou.crt -days 365
openssl x509 -in doudou.crt -text -noout

往配置文件里面增加用户认证信息:

kubectl config set-credentials doudou --client-certificate=./doudou.crt --client-key=./doudou.key --embed-certs

kubectl config view  可以看到新加的信息

切换用户

kubectl config use-context doudou@kubernetes
[root@k8s-master pki]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "doudou" cannot list resource "pods" in API group "" in the namespace "default"

上面报错是因为没有授权,只是通过认证了

切换之前的管理账号
kubectl config use-context kubernetes-admin@kubernetes

可以修改之前默认的配置文件,和其他相关的消息
[root@k8s-master ~]# kubectl config set-cluster -h

默认配置文件的认证消息在

3.  Otherwise, ${HOME}/.kube/config is used
[root@k8s-master ~]# cat .kube/config
kubectl config set-cluster  mycluster --kubeconfig=/tmp/test.conf \
 --server="https://10.211.55.11:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
kubectl config view --kubeconfig=/tmp/test.config