K8S的API Server认证介绍

Posted 有那么多的生命和爱情,在我的世界我只拥有你!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K8S的API Server认证介绍相关的知识,希望对你有一定的参考价值。

一.说明

kube-apiserver是k8s最重要的制组件之一,主要提供以下功能:

  • 提供集群管理的REST API 接口, 包括认证授权、数据校验以及集群状态变更等
  • k8s 中所有模块与 etcd 的数据交互都需要走 API Server ,禁止直接和 etcd 通信
    k8s API 的每个请求都需要经过多阶段的访问控制后才会被接受,包括认证、授权以及准入控制等。

二.认证插件

k8s的请求有两种模式:

  • 非安全模式(insecure-port):该模式下所有请求都不会经过认证,不建议开启。
  • 安全模式(secure-port):该模式下开启TLS时,所有请求都需要经过认证。k8s 支持多种认证机制,并支持同时开启多个认证插件(只要有一个认证通过即可)。如果认证成功,则用户的username 会传入授权模块进一步授权验证;对于失败认证将返回401状态码。

2.1 x509 证书

这里就是常说的ca证书, 需要在 API Server 启动时配置 --client-ca-file=xxx

2.2 静态 Token 文件

这里需要在 API Server 启动时配置 --token-auth-file=xxx。该文件为CSV文件,每行至少包括三列 token, username, user id。

2.3 引导token

  • 为了支持平滑的启动引导新的集群,k8s 包含了一种动态管理持有者令牌类型,称作启动引导令牌(Bootstrap Token)。
  • 这些令牌以 Secret 的形式保存在 kube-system 命名空间中,可以被动态管理和创建。
  • 控制器管理器包含的 TokenCleaner 控制器能够在启动引导令牌过期时将其删除。
  • 在使用 kubeadm 部署 k8s 时,可通过 kubeadm token list 命令查询。

2.4 basic auth(静态密码)

这里需要在 API Server 启动时配置 --basic-auth-file=xxx, 文件格式为 csv,每行至少三列 password, user, uid

2.5 ServiceAccount

sa(ServiceAccount) 是 k8s 比较常见的一种认证方式,每一个命名空间在创建的时候都会有一个默认的 sa, 每个 sa 都包含对应的 token

2.6 Webhook 令牌身份认证

  • --authentication-token-webhook-config-file 指向一个配置文件,描述如何访问远程的 webhook 服务。
  • --authentication-token-webhook-cache-ttl 用来设定身份认证决定的缓存时间。默认时长为 2 分钟。

鉴权

k8s 支持多种授权机制,并支持同时开启多个授权插件(只要有一个验证通过即可)。如果鉴权成功的请求将被发送到准入模块做进一步的请求验证;鉴权失败的请求则返回403。

鉴权对象

  • 用户信息:user, group, extra
  • API、请求方法(get, post 等)和请求路径(如/api)
  • 请求资源和子资源
  • Namespace
  • API Group

鉴权插件

  • ABAC
  • RBAC
  • Webhook
  • Node
    RABC(基于角色的权限控制),是目前比较流行的鉴权方式,可以将权限和角色绑定,然后将角色分配给用户,这样用户就可以自己进行授权。

RBAC使用

k8s 中的 RBAC 主要包括两种大类型,一种是基于集群的,权限将作用于整个集群的 Namespaces; 另一种是基于 Namespace 的,权限将作用于当前 Namespace

  • Role 只能作用于单个ns, ClusterRole 可以作用于多个 ns 和集群级的资源

  • 角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组鉴权对象,该鉴权对象可以是用户,组,或者 ServiceAccount

    示例:将 “pod-reader” 角色与 “default” namespace 绑定 ,并将该权限授予给"jane"

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
  name: jane # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io
  • ClusterRoleBinding 是对整个集群的授权
    示例:授权 “manager” group 组下的所有用户对集群所有 ns 的 secret-reader 权限:
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io
  • 当对组进行授权的时候,subjects name 有规定的前缀写法:需要注意的是我们在定义对象名称的时候要避免和 k8s 内置的 name 冲突
# 对 qa ns 下的所有 sa 进行授权
subjects:
- kind: Group
  name: system:serviceaccounts:qa
  apiGroup: rbac.authorization.k8s.io
# 对所有 ns 下的 sa 进行授权
subjects:
- kind: Group
  name: system:serviceaccounts
  apiGroup: rbac.authorization.k8s.io
# 对所有认证的用户进行授权
subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
# 对所有未认证的用户进行授权
subjects:
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io
# 对所有的用户进行授权
subjects:
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: system:unauthenticated
  apiGroup: rbac.authorization.k8s.io

授权实践

可以先看下集群默认管理员角色的权限:

[admin@root ~]$ kubectl get clusterrole cluster-admin -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2022-11-15T05:29:14Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
  resourceVersion: "72"
  uid: 9b2bce8b-ef75-4714-a65f-72276e7c480e
rules:
- apiGroups:
  - \'*\'
  resources:
  - \'*\'
  verbs:
  - \'*\'
- nonResourceURLs:
  - \'*\'
  verbs:
  - \'*\'

将角色与就需要将该角色与上边创建的已认证用户 itnoobzzy 进行绑定

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: default-admin
  namespace: default
subjects:
  - kind: User
    # 配置用户
    name: itnoobzzy		
    apiGroup: rbac.authorization.k8s.io
#  - kind: ServiceAccount
#    name: default
#    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

参考链接:https://blog.csdn.net/qq_42586468/article/details/128983739

k8s 组件介绍-API Server API Server简介

API Server简介

k8s API Server提供了k8s各类资源对象(pod,RC,Service等)的增删改查及watch等HTTP Rest接口,是整个系统的数据总线和数据中心。

kubernetes API Server的功能:

  1. 提供了集群管理的REST API接口(包括认证授权、数据校验以及集群状态变更);
  2. 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd);
  3. 是资源配额控制的入口;
  4. 拥有完备的集群安全机制.

kube-apiserver工作原理图

技术图片

如何访问kubernetes API

k8s通过kube-apiserver这个进程提供服务,该进程运行在单个k8s-master节点上。默认有两个端口。

k8s通过kube-apiserver这个进程提供服务,该进程运行在单个k8s-master节点上。默认有两个端口。

1. 本地端口

  1. 该端口用于接收HTTP请求;
  2. 该端口默认值为8080,可以通过API Server的启动参数“--insecure-port”的值来修改默认值;
  3. 默认的IP地址为“localhost”,可以通过启动参数“--insecure-bind-address”的值来修改该IP地址;
  4. 非认证或授权的HTTP请求通过该端口访问API Server。

2.安全端口

  1. 该端口默认值为6443,可通过启动参数“--secure-port”的值来修改默认值;
  2. 默认IP地址为非本地(Non-Localhost)网络端口,通过启动参数“--bind-address”设置该值;
  3. 该端口用于接收HTTPS请求;
  4. 用于基于Tocken文件或客户端证书及HTTP Base的认证;
  5. 用于基于策略的授权;
  6. 默认不启动HTTPS安全访问控制。

kubernetes API访问方式

Kubernetes REST API可参考https://kubernetes.io/docs/api-reference/v1.6/

1. curl

curl localhost:8080/api

curl localhost:8080/api/v1/pods

curl localhost:8080/api/v1/services

curl localhost:8080/api/v1/replicationcontrollers

2. Kubectl Proxy

Kubectl Proxy代理程序既能作为API Server的反向代理,也能作为普通客户端访问API Server的代理。通过master节点的8080端口来启动该代理程序。

kubectl proxy --port=8080 &

具体见kubectl proxy --help

3. kubectl客户端

命令行工具kubectl客户端,通过命令行参数转换为对API Server的REST API调用,并将调用结果输出。

命令格式:kubectl [command] [options]

具体可参考Kubernetes常用命令

4. 编程方式调用

使用场景:

1、运行在Pod里的用户进程调用kubernetes API,通常用来实现分布式集群搭建的目标。

2、开发基于kubernetes的管理平台,比如调用kubernetes API来完成Pod、Service、RC等资源对象的图形化创建和管理界面。可以使用kubernetes提供的Client Library。

具体可参考https://github.com/kubernetes/client-go

通过API Server访问Node、Pod和Service

k8s API Server最主要的REST接口是资源对象的增删改查,另外还有一类特殊的REST接口—k8s Proxy API接口,这类接口的作用是代理REST请求,即kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口上,由该kubelet进程负责响应。

1. Node相关接口

关于Node相关的接口的REST路径为:/api/v1/proxy/nodes/{name},其中{name}为节点的名称或IP地址。

/api/v1/proxy/nodes/{name}/pods/    #列出指定节点内所有Pod的信息

/api/v1/proxy/nodes/{name}/stats/   #列出指定节点内物理资源的统计信息

/api/v1/prxoy/nodes/{name}/spec/    #列出指定节点的概要信息

这里获取的Pod信息来自Node而非etcd数据库,两者时间点可能存在偏差。如果在kubelet进程启动时加--enable-debugging-handles=true参数,那么kubernetes Proxy API还会增加以下接口:

/api/v1/proxy/nodes/{name}/run      #在节点上运行某个容器

/api/v1/proxy/nodes/{name}/exec     #在节点上的某个容器中运行某条命令

/api/v1/proxy/nodes/{name}/attach   #在节点上attach某个容器

/api/v1/proxy/nodes/{name}/portForward   #实现节点上的Pod端口转发

/api/v1/proxy/nodes/{name}/logs     #列出节点的各类日志信息

/api/v1/proxy/nodes/{name}/metrics  #列出和该节点相关的Metrics信息

/api/v1/proxy/nodes/{name}/runningpods  #列出节点内运行中的Pod信息

/api/v1/proxy/nodes/{name}/debug/pprof  #列出节点内当前web服务的状态,包括CPU和内存的使用情况

2. Pod相关接口

/api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*}      #访问pod的某个服务接口

/api/v1/proxy/namespaces/{namespace}/pods/{name}               #访问Pod

#以下写法不同,功能一样

/api/v1/namespaces/{namespace}/pods/{name}/proxy/{path:*}      #访问pod的某个服务接口

/api/v1/namespaces/{namespace}/pods/{name}/proxy               #访问Pod

3. Service相关接口

/api/v1/proxy/namespaces/{namespace}/services/{name}

Pod的proxy接口的作用:在kubernetes集群之外访问某个pod容器的服务(HTTP服务),可以用Proxy API实现,这种场景多用于管理目的,比如逐一排查Service的Pod副本,检查哪些Pod的服务存在异常问题。

集群功能模块之间的通信

kubernetes API Server作为集群的核心,负责集群各功能模块之间的通信,集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,通过API Server提供的REST接口(GETLISTWATCH方法)来实现,从而实现各模块之间的信息交互。

1. kubelet与API Server交互

每个Node节点上的kubelet定期就会调用API Server的REST接口报告自身状态,API Server接收这些信息后,将节点状态信息更新到etcd中。kubelet也通过API Server的Watch接口监听Pod信息,从而对Node机器上的POD进行管理。

监听信息

kubelet动作

备注

新的POD副本被调度绑定到本节点 执行POD对应的容器的创建和启动逻辑  
POD对象被删除 删除本节点上相应的POD容器  
修改POD信息 修改本节点的POD容器  

2. kube-controller-manager与API Server交互

kube-controller-manager中的Node Controller模块通过API Server提供的Watch接口,实时监控Node的信息,并做相应处理。

3. kube-scheduler与API Server交互

Scheduler通过API Server的Watch接口监听到新建Pod副本的信息后,它会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑。调度成功后将Pod绑定到目标节点上。

 

技术图片

 

API Server参数介绍

API Server 主要是和 etcd 打交道,并且对外提供 HTTP 服务,以及进行安全控制,因此它的命令行提供的参数也主要和这几个方面有关。下面是一些比较重要的参数以及说明(不同版本参数可能会有不同):

参数含义默认值
–advertise-address 通过该 ip 地址向集群其他节点公布 api server 的信息,必须能够被其他节点访问 nil
–allow-privileged 是否允许 privileged 容器运行 false
–admission-control 准入控制 AlwaysAdmit
–authorization-mode 授权模式 ,安全接口上的授权 AlwaysAllow
–bind-address HTTPS 安全接口的监听地址 0.0.0.0
–secure-port HTTPS 安全接口的监听端口 6443
–cert-dir TLS 证书的存放目录 /var/run/kubernetes
–etcd-prefix 信息存放在 etcd 中地址的前缀 “/registry”
–etcd-servers 逗号分割的 etcd server 地址 []
–insecure-bind-address HTTP 访问的地址 127.0.0.1
–insecure-port HTTP 访问的端口 8080
–log-dir 日志存放的目录  
–service-cluster-ip-range service 要使用的网段,使用 CIDR 格式,参考 kubernetes 中 service 的定义  

API Server安装和运行

API Server 是通过提供的 kube-apiserver 二进制文件直接运行的,下面的例子指定了 service 分配的 ip 范围,etcd 的地址,和对外提供服务的 ip 地址:

  1.  
     /usr/bin/kube-apiserver
  2.  
     
  3.  
    --service-cluster-ip-range=10.20.0.1/24
  4.  
     
  5.  
    --etcd-servers=http://127.0.0.1:2379
  6.  
     
  7.  
    --advertise-address=192.168.8.100
  8.  
     
  9.  
    --bind-address=192.168.8.100
  10.  
     
  11.  
    --insecure-bind-address=192.168.8.100
  12.  
     
  13.  
    --v=4

直接访问 8080 端口,API Server 会返回它提供了哪些接口:

  1.  
     [root@localhost vagrant]# curl http://192.168.8.100:8080
  2.  
     
  3.  
    {
  4.  
    "paths": [
  5.  
    "/api",
  6.  
    "/api/v1",
  7.  
    "/apis",
  8.  
    "/apis/apps",
  9.  
    "/apis/apps/v1alpha1",
  10.  
    "/apis/autoscaling",
  11.  
    "/apis/autoscaling/v1",
  12.  
    "/apis/batch",
  13.  
    "/apis/batch/v1",
  14.  
    "/apis/batch/v2alpha1",
  15.  
    "/apis/extensions",
  16.  
    "/apis/extensions/v1beta1",
  17.  
    "/apis/policy",
  18.  
    "/apis/policy/v1alpha1",
  19.  
    "/apis/rbac.authorization.k8s.io",
  20.  
    "/apis/rbac.authorization.k8s.io/v1alpha1",
  21.  
    "/healthz",
  22.  
    "/healthz/ping",
  23.  
    "/logs/",
  24.  
    "/metrics",
  25.  
    "/swaggerapi/",
  26.  
    "/ui/",
  27.  
    "/version"
  28.  
    ]
  29.  
    }

而目前最重要的路径是 /api/v1,里面包含了 kubernetes 所有资源的操作,比如下面的 nodes:

  1.  
     ? ~ http http://192.168.8.100:8080/api/v1/nodes
  2.  
     
  3.  
    HTTP/1.1 200 OK
  4.  
     
  5.  
    Content-Length: 112
  6.  
     
  7.  
    Content-Type: application/json
  8.  
     
  9.  
    Date: Thu, 08 Sep 2016 08:14:45 GMT
  10.  
     
  11.  
    {
  12.  
     
  13.  
    "apiVersion": "v1",
  14.  
     
  15.  
    "items": [],
  16.  
     
  17.  
    "kind": "NodeList",
  18.  
     
  19.  
    "metadata": {
  20.  
     
  21.  
    "resourceVersion": "12",
  22.  
     
  23.  
    "selfLink": "/api/v1/nodes"
  24.  
    }
  25.  
    }

 API 以 json 的形式返回,会通过 apiVersion 来说明 API 版本号,kind 说明请求的是什么资源。不过这里面的内容是空的,因为目前还没有任何 kubelet 节点接入到我们的 API Server。对应的,pod 也是空的:

  1.  
     ? ~ http http://192.168.8.100:8080/api/v1/pods
  2.  
     
  3.  
    HTTP/1.1 200 OK
  4.  
     
  5.  
    Content-Length: 110
  6.  
     
  7.  
    Content-Type: application/json
  8.  
     
  9.  
    Date: Thu, 08 Sep 2016 08:18:53 GMT
  10.  
     
  11.  
    {
  12.  
     
  13.  
    "apiVersion": "v1",
  14.  
     
  15.  
    "items": [],
  16.  
     
  17.  
    "kind": "PodList",
  18.  
     
  19.  
    "metadata": {
  20.  
     
  21.  
    "resourceVersion": "12",
  22.  
     
  23.  
    "selfLink": "/api/v1/pods"
  24.  
     
  25.  
    }
  26.  
     
  27.  
    }

添加节点

添加节点也非常简单,启动 kubelet 的时候使用 --api-servers 指定要接入的 API Server 就行。kubelet 启动之后,会把自己注册到指定的 API Server,然后监听 API 对应 pod 的变化,根据 API 中 pod 的实际信息来管理节点上 pod 的生命周期。

现在访问 /api/v1/nodes 就能看到已经添加进来的节点:

  1.  
     ? ~ http http://192.168.8.100:8080/api/v1/nodes
  2.  
    HTTP/1.1 200 OK
  3.  
    Content-Type: application/json
  4.  
    Date: Thu, 08 Sep 2016 08:27:44 GMT
  5.  
    Transfer-Encoding: chunked
  6.  
    {
  7.  
    "apiVersion": "v1",
  8.  
    "items": [
  9.  
    {
  10.  
    "metadata": {
  11.  
    "annotations": {
  12.  
    "volumes.kubernetes.io/controller-managed-attach-detach": "true"
  13.  
    },
  14.  
    "creationTimestamp": "2016-09-08T08:23:01Z",
  15.  
    "labels": {
  16.  
    "beta.kubernetes.io/arch": "amd64",
  17.  
    "beta.kubernetes.io/os": "linux",
  18.  
    "kubernetes.io/hostname": "192.168.8.100"
  19.  
    },
  20.  
    "name": "192.168.8.100",
  21.  
    "resourceVersion": "65",
  22.  
    "selfLink": "/api/v1/nodes/192.168.8.100",
  23.  
    "uid": "74e16eba-759d-11e6-b463-080027c09e5b"
  24.  
    },
  25.  
    "spec": {
  26.  
    "externalID": "192.168.8.100"
  27.  
    },
  28.  
    "status": {
  29.  
    "addresses": [
  30.  
    {
  31.  
    "address": "192.168.8.100",
  32.  
    "type": "LegacyHostIP"
  33.  
    },
  34.  
    {
  35.  
    "address": "192.168.8.100",
  36.  
    "type": "InternalIP"
  37.  
    }
  38.  
    ],
  39.  
    "allocatable": {
  40.  
    "alpha.kubernetes.io/nvidia-gpu": "0",
  41.  
    "cpu": "1",
  42.  
    "memory": "502164Ki",
  43.  
    "pods": "110"
  44.  
    },
  45.  
    "capacity": {
  46.  
    "alpha.kubernetes.io/nvidia-gpu": "0",
  47.  
    "cpu": "1",
  48.  
    "memory": "502164Ki",
  49.  
    "pods": "110"
  50.  
    },
  51.  
    "conditions": [
  52.  
    {
  53.  
    "lastHeartbeatTime": "2016-09-08T08:27:36Z",
  54.  
    "lastTransitionTime": "2016-09-08T08:23:01Z",
  55.  
    "message": "kubelet has sufficient disk space available",
  56.  
    "reason": "KubeletHasSufficientDisk",
  57.  
    "status": "False",
  58.  
    "type": "OutOfDisk"
  59.  
    },
  60.  
    {
  61.  
    "lastHeartbeatTime": "2016-09-08T08:27:36Z",
  62.  
    "lastTransitionTime": "2016-09-08T08:23:01Z",
  63.  
    "message": "kubelet has sufficient memory available",
  64.  
    "reason": "KubeletHasSufficientMemory",
  65.  
    "status": "False",
  66.  
    "type": "MemoryPressure"
  67.  
    },
  68.  
    {
  69.  
    "lastHeartbeatTime": "2016-09-08T08:27:36Z",
  70.  
    "lastTransitionTime": "2016-09-08T08:24:56Z",
  71.  
    "message": "kubelet is posting ready status",
  72.  
    "reason": "KubeletReady",
  73.  
    "status": "True",
  74.  
    "type": "Ready"
  75.  
    }
  76.  
    ],
  77.  
    "daemonEndpoints": {
  78.  
    "kubeletEndpoint": {
  79.  
    "Port": 10250
  80.  
    }
  81.  
    },
  82.  
    "images": [
  83.  
    {
  84.  
    "names": [
  85.  
    "172.16.1.41:5000/nginx:latest"
  86.  
    ],
  87.  
    "sizeBytes": 425626718
  88.  
    },
  89.  
    {
  90.  
    "names": [
  91.  
    "172.16.1.41:5000/hyperkube:v0.18.2"
  92.  
    ],
  93.  
    "sizeBytes": 207121551
  94.  
    },
  95.  
    {
  96.  
    "names": [
  97.  
    "172.16.1.41:5000/etcd:v3.0.4"
  98.  
    ],
  99.  
    "sizeBytes": 43302056
  100.  
    },
  101.  
    {
  102.  
    "names": [
  103.  
    "172.16.1.41:5000/busybox:latest"
  104.  
    ],
  105.  
    "sizeBytes": 1092588
  106.  
    },
  107.  
    {
  108.  
    "names": [
  109.  
    "172.16.1.41:5000/google_containers/pause:0.8.0"
  110.  
    ],
  111.  
    "sizeBytes": 241656
  112.  
    }
  113.  
    ],
  114.  
    "nodeInfo": {
  115.  
    "architecture": "amd64",
  116.  
    "bootID": "48955926-11dd-4ad3-8bb0-2585b1c9215d",
  117.  
    "containerRuntimeVersion": "docker://1.10.3",
  118.  
    "kernelVersion": "3.10.0-123.13.1.el7.x86_64",
  119.  
    "kubeProxyVersion": "v1.3.1-beta.0.6+fbf3f3e5292fb0",
  120.  
    "kubeletVersion": "v1.3.1-beta.0.6+fbf3f3e5292fb0",
  121.  
    "machineID": "b9597c4ae5f24494833d35e806e00b29",
  122.  
    "operatingSystem": "linux",
  123.  
    "osImage": "CentOS Linux 7 (Core)",
  124.  
    "systemUUID": "823EB67A-057E-4EFF-AE7F-A758140CD2F7"
  125.  
    }
  126.  
    }
  127.  
    }
  128.  
    ],
  129.  
    "kind": "NodeList",
  130.  
    "metadata": {
  131.  
    "resourceVersion": "65",
  132.  
    "selfLink": "/api/v1/nodes"
  133.  
    }
  134.  
    }

 我们可以看到,kubelet 收集了很多关于自身节点的信息,这些信息也会不断更新。这些信息里面不仅包含节点的系统信息(系统架构,操作系统版本,内核版本等)、还有镜像信息(节点上有哪些已经下载的 docker 镜像)、资源信息(Memory 和 Disk 的总量和可用量)、以及状态信息(是否正常,可以分配 pod等)。

和 API Server 通信

编写的 yaml 文件转换成 json 格式,保存到文件里。主要注意的是,我们指定了 nodeName 的名字,这个名字必须和之前通过 /api/v1/nodes 得到的结果中 metadata.labels.kubernetes.io/hostname 保持一致:

  1.  
     [root@localhost vagrant]# cat nginx_pod.yml
  2.  
    apiVersion: v1
  3.  
    kind: Pod
  4.  
    metadata:
  5.  
    name: nginx-server
  6.  
    spec:
  7.  
    NodeName: 192.168.8.100
  8.  
    containers:
  9.  
    - name: nginx-server
  10.  
    image: 172.16.1.41:5000/nginx
  11.  
    ports:
  12.  
    - containerPort: 80
  13.  
    volumeMounts:
  14.  
    - mountPath: /var/log/nginx
  15.  
    name: nginx-logs
  16.  
    - name: log-output
  17.  
    image: 172.16.1.41:5000/busybox
  18.  
    command:
  19.  
    - bin/sh
  20.  
    args: [-c, ‘tail -f /logdir/access.log‘]
  21.  
    volumeMounts:
  22.  
    - mountPath: /logdir
  23.  
    name: nginx-logs
  24.  
    volumes:
  25.  
    - name: nginx-logs
  26.  
    emptyDir: {}

 

使用 curl 执行 POST 请求,设置头部内容为 application/json,传过去文件中的 json 值,可以看到应答(其中 status 为 pending,表示以及接收到请求,正在准备处理):

  1.  
    # curl -s -X POST -H "Content-Type: application/json" http://192.168.8.100:8080/api/v1/namespaces/default/pods --data @nginx_pod.json
  2.  
    {
  3.  
    "kind": "Pod",
  4.  
    "apiVersion": "v1",
  5.  
    "metadata": {
  6.  
    "name": "nginx-server",
  7.  
    "namespace": "default",
  8.  
    "selfLink": "/api/v1/namespaces/default/pods/nginx-server",
  9.  
    "uid": "888e95d0-75a9-11e6-b463-080027c09e5b",
  10.  
    "resourceVersion": "573",
  11.  
    "creationTimestamp": "2016-09-08T09:49:28Z"
  12.  
    },
  13.  
    "spec": {
  14.  
    "volumes": [
  15.  
    {
  16.  
    "name": "nginx-logs",
  17.  
    "emptyDir": {}
  18.  
    }
  19.  
    ],
  20.  
    "containers": [
  21.  
    {
  22.  
    "name": "nginx-server",
  23.  
    "image": "172.16.1.41:5000/nginx",
  24.  
    "ports": [
  25.  
    {
  26.  
    "containerPort": 80,
  27.  
    "protocol": "TCP"
  28.  
    }
  29.  
    ],
  30.  
    "resources": {},
  31.  
    "volumeMounts": [
  32.  
    {
  33.  
    "name": "nginx-logs",
  34.  
    "mountPath": "/var/log/nginx"
  35.  
    }
  36.  
    ],
  37.  
    "terminationMessagePath": "/dev/termination-log",
  38.  
    "imagePullPolicy": "Always"
  39.  
    }
  40.  
    ],
  41.  
    "restartPolicy": "Always",
  42.  
    "terminationGracePeriodSeconds": 30,
  43.  
    "dnsPolicy": "ClusterFirst",
  44.  
    "nodeName": "192.168.8.100",
  45.  
    "securityContext": {}
  46.  
    },
  47.  
    "status": {
  48.  
    "phase": "Pending"
  49.  
    }
  50.  
    }

返回中包含了我们提交 pod 的信息,并且添加了 statusmetadata 等额外信息。

等一段时间去查询 pod,就可以看到 pod 的状态已经更新了:

  1.  
     ? http http://192.168.8.100:8080/api/v1/namespaces/default/pods
  2.  
    HTTP/1.1 200 OK
  3.  
    Content-Type: application/json
  4.  
    Date: Thu, 08 Sep 2016 09:51:29 GMT
  5.  
    Transfer-Encoding: chunked
  6.  
    {
  7.  
    "apiVersion": "v1",
  8.  
    "items": [
  9.  
    {
  10.  
    "metadata": {
  11.  
    "creationTimestamp": "2016-09-08T09:49:28Z",
  12.  
    "name": "nginx-server",
  13.  
    "namespace": "default",
  14.  
    "resourceVersion": "592",
  15.  
    "selfLink": "/api/v1/namespaces/default/pods/nginx-server",
  16.  
    "uid": "888e95d0-75a9-11e6-b463-080027c09e5b"
  17.  
    },
  18.  
    "spec": {
  19.  
    "containers": [
  20.  
    {
  21.  
    "image": "172.16.1.41:5000/nginx",
  22.  
    "imagePullPolicy": "Always",
  23.  
    "name": "nginx-server",
  24.  
    "ports": [
  25.  
    {
  26.  
    "containerPort": 80,
  27.  
    "protocol": "TCP"
  28.  
    }
  29.  
    ],
  30.  
    "resources": {},
  31.  
    "terminationMessagePath": "/dev/termination-log",
  32.  
    "volumeMounts": [
  33.  
    {
  34.  
    "mountPath": "/var/log/nginx",
  35.  
    "name": "nginx-logs"
  36.  
    }
  37.  
    ]
  38.  
    },
  39.  
    {
  40.  
    "args": [
  41.  
    "-c",
  42.  
    "tail -f /logdir/access.log"
  43.  
    ],
  44.  
    "command": [
  45.  
    "bin/sh"
  46.  
    ],
  47.  
    "image": "172.16.1.41:5000/busybox",
  48.  
    "imagePullPolicy": "Always",
  49.  
    "name": "log-output",
  50.  
    "resources": {},
  51.  
    "terminationMessagePath": "/dev/termination-log",
  52.  
    "volumeMounts": [
  53.  
    {
  54.  
    "mountPath": "/logdir",
  55.  
    "name": "nginx-logs"
  56.  
    }
  57.  
    ]
  58.  
    }
  59.  
    ],
  60.  
    "dnsPolicy": "ClusterFirst",
  61.  
    "nodeName": "192.168.8.100",
  62.  
    "restartPolicy": "Always",
  63.  
    "securityContext": {},
  64.  
    "terminationGracePeriodSeconds": 30,
  65.  
    "volumes": [
  66.  
    {
  67.  
    "emptyDir": {},
  68.  
    "name": "nginx-logs"
  69.  
    }
  70.  
    ]
  71.  
    },
  72.  
    "status": {
  73.  
    "conditions": [
  74.  
    {
  75.  
    "lastProbeTime": null,
  76.  
    "lastTransitionTime": "2016-09-08T09:49:28Z",
  77.  
    "status": "True",
  78.  
    "type": "Initialized"
  79.  
    },
  80.  
    {
  81.  
    "lastProbeTime": null,
  82.  
    "lastTransitionTime": "2016-09-08T09:49:44Z",
  83.  
    "status": "True",
  84.  
    "type": "Ready"
  85.  
    },
  86.  
    {
  87.  
    "lastProbeTime": null,
  88.  
    "lastTransitionTime": "2016-09-08T09:49:44Z",
  89.  
    "status": "True",
  90.  
    "type": "PodScheduled"
  91.  
    }
  92.  
    ],
  93.  
    "containerStatuses": [
  94.  
    {
  95.  
    "containerID": "docker://8b79eeea60f27b6d3f0a19cbd1b3ee3f83709bcf56574a6e1124c69a6376972d",
  96.  
    "image": "172.16.1.41:5000/busybox",
  97.  
    "imageID": "docker://sha256:8c566faa3abdaebc33d40c1b5e566374c975d17754c69370f78c00c162c1e075",
  98.  
    "lastState": {},
  99.  
    "name": "log-output",
  100.  
    "ready": true,
  101.  
    "restartCount": 0,
  102.  
    "state": {
  103.  
    "running": {
  104.  
    "startedAt": "2016-09-08T09:49:43Z"
  105.  
    }
  106.  
    }
  107.  
    },
  108.  
    {
  109.  
    "containerID": "docker://96e64cdba7b05d4e30710a20e958ff5b8f1f359c8d16d32622b36f0df0cb353c",
  110.  
    "image": "172.16.1.41:5000/nginx",
  111.  
    "imageID": "docker://sha256:51d764c1fd358ce81fd0e728436bd0175ff1f3fd85fc5d1a2f9ba3e7dc6bbaf6",
  112.  
    "lastState": {},
  113.  
    "name": "nginx-server",
  114.  
    "ready": true,
  115.  
    "restartCount": 0,
  116.  
    "state": {
  117.  
    "running": {
  118.  
    "startedAt": "2016-09-08T09:49:36Z"
  119.  
    }
  120.  
    }
  121.  
    }
  122.  
    ],
  123.  
    "hostIP": "192.168.8.100",
  124.  
    "phase": "Running",
  125.  
    "podIP": "172.17.0.2",
  126.  
    "startTime": "2016-09-08T09:49:28Z"
  127.  
    }
  128.  
    }
  129.  
    ],
  130.  
    "kind": "PodList",
  131.  
     
  132.  
    "metadata": {
  133.  
    "resourceVersion": "602",
  134.  
    "selfLink": "/api/v1/namespaces/default/pods"
  135.  
    }
  136.  
    }

可以看到 pod 已经在运行,并且给分配了 ip:172.17.0.2,通过 curl 也可以访问它的服务:

  1.  
    [root@localhost vagrant]# curl -s http://172.17.0.2 | head -n 5
  2.  
    <!DOCTYPE html>
  3.  
    <html>
  4.  
    <head>
  5.  
    <title>Welcome to nginx on Debian!</title>
  6.  
    <style>

kubectl -s http://ip:8080 get pods

以上是关于K8S的API Server认证介绍的主要内容,如果未能解决你的问题,请参考以下文章

k8s使用自定义证书将客户端认证接入到API Server

关于Kubernetes中API Server使用tokenkubeconfig文件认证的一些笔记

k8s中各组件和kube apiserver通信时的认证和鉴权

kubernetes Server API 证书renew

使用证书认证方式配置k8s全局只读权限

调用k8s API