• Kubernetes APIServer 最佳实践



    1. kubernetes 整体架构

    kubernetes 由 master 节点和工作节点组成。其中,master 节点的组件有 APIServer,scheduler 和 controller-manager。APIServer 是系统管理指令的统一入口,scheduler 负责调度 Pod 到合适的工作节点上,controller-manager 是一组资源控制器,负责控制管理对应的资源,如 replication 等。工作节点的组件有 kubelet 和 kube-proxy。kubelet 负责创建,管理,维护 pod,kube-proxy 负责将访问 service 的流量转发到对应的 endpoint 上。

    kubernetes 的整体架构图如下所示:

    了解了整体架构图,那么各个组件是如何协同工作的呢。这里以创建 pod 为例查看各组件的协作流程,流程图如下:

    主要有如下几步:

    1. 用户调用 REST API 请求创建 pod,APIServer 响应 API 请求,并进行一系列验证操作,包括认证,授权和资源配置等,验证通过后,APIServer 调用 etcd 在后台数据库建立 Pod 资源对象。
    2. scheduler 定期调用 APIServer 的 kubernetes API 接口查看系统中可用的工作节点列表和待调度 Pod,使用调度策略为待调度 Pod 选择合适的工作节点,这个过程称为绑定(bind)。
    3. 绑定成功后,scheduler 调用 APIServer 在 etcd 中创建 binding 对象,该对象描述了工作节点上绑定运行的所有 pod 信息。

    1.1 APIServer 概述

    APIServer 作为统一接口,负责管理各组件的通信,是 kubernetes 集群的核心。对资源的增删改查操作都将通过 APIServer 传递到后台 etcd 数据库,使用 curl 工具可以很容易的获取到 APIServer 的 API 响应信息。

    1.1.1 Kubernetes APIServer 组件

    查看环境上运行的 APIServer:

    [root@chunqiu ~ (Master)]# kubectl get pods -o wide -n kube-system | grep api
    kube-apiserver-chunqiu-0            1/1     Running   1          70d    172.17.66.2     chunqiu-0   <none>           <none>
    kube-apiserver-chunqiu-1            1/1     Running   1          70d    172.17.66.3     chunqiu-1   <none>           <none>
    kube-apiserver-chunqiu-2            1/1     Running   1          70d    172.17.66.4     chunqiu-2   <none>           <none>
    
    [root@chunqiu ~ (Master)]# kubectl get service -o wide
    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
    kubernetes   ClusterIP   10.254.0.1   <none>        443/TCP   70d   <none>
    
    [root@chunqiu ~ (Master)]# kubectl describe service kubernetes
    Name:              kubernetes
    Namespace:         default
    Labels:            component=apiserver
                       provider=kubernetes
    Annotations:       <none>
    Selector:          <none>
    Type:              ClusterIP
    IP:                10.254.0.1
    Port:              https  443/TCP
    TargetPort:        8443/TCP
    Endpoints:         172.17.66.2:8443,172.17.66.3:8443,172.17.66.4:8443
    Session Affinity:  None
    Events:            <none>
    

    当前环境为 master 和工作节点共用模式,可以看到每台节点上都以 pod 形式运行了 APIServer,并且它们与 kubernetes service 进行了绑定。

    集群内的 APIServer 部署知道了,那 APIServer 的配置文件又是怎样的呢?查看组件的配置文件能更好的理解组件的整体结构:

    [root@chunqiu ~ (Master)]# kubectl describe pods kube-apiserver-chunqiu-0 -n kube-system
    Priority:             2000001000
    Priority Class Name:  system-node-critical
    Status:               Running
    IP:                   172.17.66.2
    Containers:
      kube-apiserver:
        Image:         bcmt-registry:5000/k8s.gcr.io/kube-apiserver-amd64:v1.19.5
        Port:          8443/TCP
        Host Port:     8443/TCP
        Command:
          /usr/local/bin/kube-apiserver
          --default-not-ready-toleration-seconds=180
          --default-unreachable-toleration-seconds=180
          --bind-address=172.17.66.2
          --etcd-servers=https://172.17.66.2:2379
          --etcd-cafile=/etc/etcd/ssl/ca.pem
          --etcd-certfile=/etc/etcd/ssl/etcd-client.pem
          --etcd-keyfile=/etc/etcd/ssl/etcd-client-key.pem
          --allow-privileged=true
          --service-cluster-ip-range=10.254.0.0/16
          --secure-port=8443
          --insecure-port=0
          --anonymous-auth=false
          --authorization-mode=Node,RBAC
          --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount...
          --kubelet-certificate-authority=/etc/kubernetes/ssl/ca.pem
          --kubelet-client-certificate=/etc/kubernetes/ssl/cluster-admin.pem
          --kubelet-client-key=/etc/kubernetes/ssl/cluster-admin-key.pem
    ...
    

    省略了部分参数,主要配置参数及命令如下:

    参数 描述
    /usr/local/bin/kube-apiserver image 中包含的启动 apiserver 命令
    bind-address apiserver 安全端口绑定的 ip 地址,用于接受安全连接
    etcd-servers,etcd-cafile,etcd-certfile,etcd-keyfile 访问 etcd 需要的信息
    allow-privileged 是否运行容器以特权模式运行
    service-cluster-ip-range 绑定 service 的 ip 范围(kubernetes service 的 cluster ip 为 10.254.0.1)
    secure-port 安全端口,通过安全 ip 加安全端口的方式可以访问到 apiserver
    insecure-port 非安全端口,用于接受非安全连接,0 表示不启用非安全端口
    enable-admission-plugins admission controller 的插件
    kubelet-certificate-authority,kubelet-client-certificate,kubelet-client-key 访问 apiserver 的认证信息

    介绍了 APIServer 配置信息,接下来使用 curl 调用 APIServer API 看看请求结果。

    1.1.2 Kubernetes API

    为了兼容旧版本的同时升级新版本 API,Kubernetes 提供了多版本 API 的支持,每个版本的 API 通过一个版本号路径前缀进行区分,如 /api/v1beta1 等。通过 kubectl api-version 命令可以查看当前 kubernetes 的版本信息:

    [root@chunqiu ~ (Master)]# kubectl api-versions | grep v1
    networking.k8s.io/v1
    networking.k8s.io/v1beta1
    ...
    

    可以看到资源 networking 包含不同的 APIVersion,其中 v1beta1 表示不建议使用(Deprecated)版本。关于版本发布及管理信息可看这里

    kubernetes 使用 API Groups 对 API 进行标识,API Groups 分为两种:

    1. Core Groups(核心组)是 Kubernetes 最核心的 API,其特点是没有“组”的概念,例如 “v1” 即表示核心组 apiVersion: v1。
    2. 具有分组信息的 API,以 /api/$GROUP_NAME/$VERSION/ URL 路径进行标识,如 apiVersion: apps/v1。
      关于 API 详细信息可参考这里

    以 pod 为例,查看 pod 的基本 API 接口:

    资源类型 方法 说明 备注
    PODS GET /api/v1/pods 获取 pod 列表
    POST /api/v1/pods 创建 pod 列表
    GET /api/v1/namespaces/{namespace}/pods 获取 Namespace 下的 pod 列表
    POST /api/v1/namespaces/{namespace}/pods 在 Namespace 下创建 pod
    DELETE /api/v1/namespaces/{namespace}/pods/{name} 删除 Namespace 下的 pod 对象
    GET /api/v1/namespaces/{namespace}/pods/{name} 获取 Namespace 下的 pod 对象
    PATCH /api/v1/namespaces/{namespace}/pods/{name} 部分更新某个 Namespace 下的 pod 对象
    PUT /api/v1/namespaces/{namespace}/pods/{name} 替换某个 Namespace 下的 pod 对象

    使用 curl 工具 curl pod 的 API:

    [root@chunqiu ~ (Master)]# curl https://172.17.66.2:8443/api/v1/namespaces/ci/pods/ --cacert /etc/kubernetes/ssl/ca.pem  
    --key /etc/kubernetes/ssl/cluster-admin-key.pem --cert /etc/kubernetes/ssl/cluster-admin.pem
    {
      "kind": "PodList",
      "apiVersion": "v1",
      "metadata": {
        "selfLink": "/api/v1/namespaces/ci/pods/",
        "resourceVersion": "42384766"
      },
      "items": [
        {
          "metadata": {
            "name": "chunqiu-0",
            "generateName": "chunqiu-",
            "namespace": "ci",
            "selfLink": "/api/v1/namespaces/ci/pods/chunqiu-0",
            "uid": "36793f0c-9bf9-4bec-b46e-66f5945d3889",
            "resourceVersion": "42378305",
            "creationTimestamp": "2021-06-09T03:18:00Z",
    ...
    

    curl 获取到 Namespace ci 下的 pod 列表。类似的,获取 apiVersion: apps/v1 的 statefulset 资源列表如下:

    [root@chunqiu ~ (Master)]# curl https://172.17.66.2:8443/apis/apps/v1/namespaces/ci/statefulsets/ --cacert /etc/kubernetes/ssl/ca.pem 
    --key /etc/kubernetes/ssl/cluster-admin-key.pem --cert /etc/kubernetes/ssl/cluster-admin.pem
    {
      "kind": "StatefulSetList",
      "apiVersion": "apps/v1",
      "metadata": {
        "selfLink": "/apis/apps/v1/namespaces/ci/statefulsets/",
        "resourceVersion": "42392636"
      },
      "items": [
        {
          "metadata": {
            "name": "chunqiu",
            "namespace": "ci",
            "selfLink": "/apis/apps/v1/namespaces/ci/statefulsets/chunqiu",
            "uid": "0e00ffab-e504-43bf-bcd6-713359a2cfde",
            "resourceVersion": "42392038",
            "generation": 1,
            "creationTimestamp": "2021-06-09T03:40:55Z",
            "labels": {
              "app.kubernetes.io/managed-by": "Helm"
            },
    ...
    

    对资源对象的操作除了增删改查外,Kubernetes 还提供另外一种资源操作类型 WATCH,WATCH 返回一连串 JSON 对象,该对象记录了某个给定资源对象的变化情况。如对 pod 的 WATCH 操作:

    资源类型 类型 方法 URL Path 说明
    PODS WATCH GET /api/v1/watch/pods 监听所有 pod 变化
    POST /api/v1/watch/namespaces/{namespace}/pods 监听某个 Namespace 下所有 pod 的变化

    调用 WATCH API 监听 pod 变化情况:

    [root@chunqiu ~ (Master)]# curl https://172.17.66.2:8443/api/v1/watch/pods/ --cacert /etc/kubernetes/ssl/ca.pem
    --key /etc/kubernetes/ssl/cluster-admin-key.pem --cert /etc/kubernetes/ssl/cluster-admin.pem
    {"type":"ADDED","object":{"kind":"Pod","apiVersion":"v1"
    ...
    
    # 删除 pod
    {"type":"MODIFIED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"chunqiu-0","generateName":"chunqiu-...
    ...
    

    可以看到 WATCH API 始终处于监控当前 pod 变化状态,使用 kubectl 删除某个 pod,WATCH API 监听到该 pod 的变化情况。

    1.2 etcd 概述

    那么 APIServer 介绍完了吗?并没有,离开 etcd 的 APIServer 是不完整的。介绍 etcd 之前,先看下 APIServer 的拓扑结构:

    用户请求通过认证授权之后访问 APIServer,APIServer 会进一步调用 admission controller 对用户请求进行进一步资源审核,审核由多维度资源插件完成(APIServer 配置参数的 enable-admission-plugins 参数定义了所需资源审核插件),通过审核后 APIServer 会根据 REST API 调用在后台 etcd 进行实际的增删改查操作。

    Kubernetes 的资源存储路径都以 /registry 开始的:

    [root@chunqiu ~ (Master)]# etcdctl --endpoints=https://172.17.66.2:2379 --cacert /etc/etcd/ssl/ca.pem 
    --key /etc/etcd/ssl/etcd-key.pem --cert /etc/etcd/ssl/etcd.pem get /registry/ --prefix --keys-only=true
    /registry/apiextensions.k8s.io/customresourcedefinitions/brhooks.cbur.csf.chunqiu.com
    
    /registry/apiextensions.k8s.io/customresourcedefinitions/brpolices.cbur.bcmt.local
    ...
    

    构造场景使用 DELETE 方法删除 pod,查看 etcd 中该 pod 的资源变化情况:

    1. 默认 namespace 下创建 pod,查看 pod 在 etcd 存储情况。
    [root@chunqiu ~ (Master)]# kubectl get pods
    NAME         READY   STATUS             RESTARTS   AGE
    etcdtester   0/1     ImagePullBackOff   0          100s
    
    [root@chunqiu ~ (Master)]# etcdctl --endpoints=https://172.17.66.2:2379 --cacert /etc/etcd/ssl/ca.pem 
    --key /etc/etcd/ssl/etcd-key.pem --cert /etc/etcd/ssl/etcd.pem get /registry/pods/default/etcdtester --prefix --keys-only=true
    /registry/pods/default/etcdtester
    
    1. 开启 WATCH 监听默认 namespace 下 pod 变化情况。
    [root@chunqiu ~ (Master)]# curl https://172.17.66.2:8443/api/v1/watch/namespaces/default/pods/ --cacert /etc/kubernetes/ssl/ca.pem 
    --key /etc/kubernetes/ssl/cluster-admin-key.pem --cert /etc/kubernetes/ssl/cluster-admin.pem
    {"type":"ADDED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"etcdtester"...
    
    
    1. 调用 APIServer 的 DELETE 方法删除 pod,查看 etcd 中 pod 变化情况:
    # DELETE pod
    [root@chunqiu ~ (Master)]# curl -X DELETE https://172.17.66.2:8443/api/v1/namespaces/default/pods/etcdtester --cacert /etc/kubernetes/ssl/ca.pem 
    --key /etc/kubernetes/ssl/cluster-admin-key.pem --cert /etc/kubernetes/ssl/cluster-admin.pem
    {
      "kind": "Pod",
      "apiVersion": "v1",
      "metadata": {
        "name": "etcdtester",
        "namespace": "default",
        "selfLink": "/api/v1/namespaces/default/pods/etcdtester",
    ...
    
    # WATCH 监听 pod
    [root@chunqiu ~ (Master)]# curl https://172.17.66.2:8443/api/v1/watch/namespaces/default/pods/ --cacert /etc/kubernetes/ssl/ca.pem 
    --key /etc/kubernetes/ssl/cluster-admin-key.pem --cert /etc/kubernetes/ssl/cluster-admin.pem
    {"type":"ADDED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"etcdtester"...
    
    {"type":"MODIFIED","object":{"kind":"Pod","apiVersion":"v1","metadata":{"name":"etcdtester"...
    
    # etcd 查看 pod
    [root@chunqiu ~ (Master)]# etcdctl --endpoints=https://172.17.66.2:2379 --cacert /etc/etcd/ssl/ca.pem 
    --key /etc/etcd/ssl/etcd-key.pem --cert /etc/etcd/ssl/etcd.pem get /registry/pods/default/etcdtester --prefix --keys-only=true
    

    可以看到,删除 pod 后 WATCH 监听到 pod 变化,etcd 更新 pod 资源对象。

    芝兰生于空谷,不以无人而不芳。
  • 相关阅读:
    Thread记录
    反射的学习笔记--sql语句生成
    Index was outside the bounds of the array. (Microsoft.SqlServer.Smo)
    contains 方法
    mysql connector 和 sqlserver ado.net 的区别
    javascript slice
    javascript bind
    转,SelectNodes + XPath
    jsgen 搭建
    【转】基于第一个PhoneGap(cordova)的应用详解
  • 原文地址:https://www.cnblogs.com/xingzheanan/p/14867340.html
Copyright © 2020-2023  润新知