客户端请求API Server过程

客户端 --> API Server(识别用户是否有通过api server执行操作的权限)
  api Server识别内容:
    user: username,uid
    group: 用户组
    extra: 字段,提供额外信息

 

客户端请求的API(Request Path):
例如客户端对一个k8s集群中的名为myapp-deploy的deployment的资源发起请求,地址为下,成功的话则可进行增删改查;
  http://192.168.133.128:6443/apis/apps/v1/namespaces/default/deployments/myapp-deploy

  注释:
    192.168.222.100: master地址
    6443: API server端口
    apis: 固定入口(除核心群组(/api/v1/)外)
    apps: app组
    v1: 组版本
    namespaces: 名称空间级别
    default: 名称空间的名称
    deployments: 访问deployment资源
    myapp-deploy: deployment名称

请求操作(action):
  http的方法请求:
    get
    post
    put
    delete
  k8s请求动作:
    增: create
    删: delete,deletecollection(删除一个集合)
    改: edit,patch
    查: get,list,watch(-w)

API Server是整个访问请求进入的网关接口,请求过程中
  认证用于实现身份识别;
  授权用于实现权限检查,检查用户是否拥有对资源执行各种k8s请求动作;
  准入控制机制用来进一步补充授权机制,创建、删除、修改时需要;


k8s集群有两类认证时的认证账号:
1. useraccount
2. serviceaccount

访问API Server的客户端分为以下两类:
  1. 集群之外的客户端访问节点地址进行通信;
  2. 集群内部的Pod等,使用API Server在集群内的地址(kubectl get svc(kubernetes这个svc),将集群外部地址引入到集群内部供内部组件使用;

  # 经过查看某一个Pod的详细信息发现Pod会自动拥有一个Volumes,这个Volumes的名称叫做"default-token-ppzsj"也就是令牌,这就是Pod连接API Server的认证信息,通过secret来定义,并以存储卷的方式关联到Pod上,
使Pod内的运行的应用通过对应的secret中保存的认证信息连接API Server来完成认证的;

$ kubectl describe pod deploy-demo-854b57c687-f7txr
....
Volumes:
default-token-ppzsj:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-ppzsj
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
....

# 经查,发现每个名称空间下都会有一个默认的secret(default-token-ppzsj)

$ kubectl get secret
NAME             TYPE               DATA   AGE
default-token-ppzsj kubernetes.io/service-account-token 3   26d

创建Pod与API Server通信的serviceaccount(与权限无关,仅认证):

# 首先查看系统上已有的serviceaccount;
$ kubectl get serviceaccount
NAME     SECRETS    AGE
default     1       26d

# 直接使用create创建一个名为admin的sa;
$ kubectl create sa admin

# 再次查询,发现创建成功;
$ kubectl get sa
NAME   SECRETS   AGE
admin     1      84s
default   1      26d

# 查看sa的详细信息,发现了名为"admin-token-pfp5j"的secret;
$ kubectl describe sa admin
Name: admin
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: admin-token-pfp5j
Tokens: admin-token-pfp5j
Events: <none>

# 查看secret,发现刚创建的sa自动创建了一个"admin-token-pfp5j"secret;
$ kubectl get secret
NAME               TYPE               DATA   AGE
admin-token-pfp5j kubernetes.io/service-account-token    3   2m32s
default-token-ppzsj kubernetes.io/service-account-token   3   26d

# 创建Pod使用新创建的sa;
$ vim pod-sa.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-sa
  namespace: default
spec:
  containers:
  - name: sa-container
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
  # 自定义serviceaccount的名称
  serviceAccountName: admin

$ kubectl apply -f pod-sa.yaml

# 查看详细信息发现默认自带的volumes中的名称变为了"admin-token-pfp5j"也就是我们刚创建sa后,集群自动帮我们创建的secret;
$ kubectl describe pods pod-sa
....
Volumes:
admin-token-pfp5j:
Type: Secret (a volume populated by a Secret)
SecretName: admin-token-pfp5j
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
....

 

配置文件连接API Server:
  API Server的客户端在认证时,如果我们要基于配置文件来保存客户端的认证信息,就要配置个配置文件,k8s集群中的所有组件,除API Server外都需要连接至API Server,都需要被API Server认证
每一个组件为了能够连入正确的集群,提供正确的账号、证书、私钥等认证信息,需要将这些信息保存为配置文件(kubeconfig),也就是API Server的客户端连入API Server时使用的认证格式的配置文件;

# 查看配置
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.133.128: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

注释:
  clusters: 集群列表,可以包含多个集群
  certificate-authority-data: 认证方式
  server: API Server路径
  name: 集群名称
  users: 用户列表
  name: 用户账号名
  client-certificate-data: 客户端证书
  client-key-data: 客户端私钥
  contexts: 上下文列表,一个上下文用来指明哪个账号管理哪个集群;
  cluster: 访问哪个集群
  user: 使用哪个用户
  name: 给上下文取名
  current-context: 当前上下文,当前使用哪个账号管理哪个集群;

由于客户端连入API Server要做双向认证,所以可以去"/etc/kubernetes/pki"目录下找到各种key、ca;

 

创建新账号来连接API Server

# cd /etc/kubernetes/pki
# (umask 077; openssl genrsa -out kfree.key 2048)
# openssl req -new -key kfree.key -out kfree.csr -subj "/CN=kfree"
# openssl x509 -req -in kfree.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out kfree.crt -days 365
# su - kubeadm
$ kubectl config set-credentials kfree --client-certificate=/etc/kubernetes/pki/kfree.crt --client-key=/etc/kubernetes/pki/kfree.key
$ kubectl config set-context kfree@kubernetes --cluster=kubernetes --user=kfree
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.133.128:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kfree
name: kfree@kubernetes
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kfree
user:
client-certificate: /etc/kubernetes/pki/kfree.crt
client-key: /etc/kubernetes/pki/kfree.key
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
$ kubectl config use-context kfree@kubernetes # 因为我们只处理了认证,没有授予权限,所以没有权限的; $ kubectl get pods Error from server (Forbidden): pods is forbidden: User "kfree" cannot list resource "pods" in API group "" in the namespace "default"

 

Logo

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

更多推荐