k8s-apiserver 参数

大番茄 2019年10月30日 1,796次浏览
--logtostderr                    # 是否把日志打印到标准错误输出
--log-dir                        # 日志目录
--etcd-servers                   # etcd
--etcd-cafile                    # 用来认证etcd的ca证书
--etcd-certfile                   # 用来连接etcd的证书。
--etcd-keyfile
--bind-address                    # 监听的有安全连接(https)的ip地址。
--advertise-address               # 要广播给集群成员的ip地址, 必须要能够访问, 如果为空,就是--bind-address的地址,如果都没有,则为机器默认地址。
--secure-port                     # https安全连接的端口
--tls-cert-file                   # apiserver https的证书。
--tls-private-key-file
--service-cluster-ip-range        # service ip 范围, 不能与pod ip范围冲突。
--service-node-port-range         # service nodePort 范围
--allow-privileged                # 是否允许特权容器。
--kubelet-https                   # 使用https连接kubelet, 执行kubectl log, exec之类的操作,apiserver需要连接kubelet。 默认就是true
--master-service-namespace        # kubernetes service放到哪个namespace,  默认default。

# 准入控制
--admission-control                    # 使用enable-admission-plugins 或 disable-admission-plugins代替, 未来版本会删除这个参数。
--enable-admission-plugins        # 启用的准入控制插件。
--disable-admission-plugins        # 关闭的准入插件。

# 认证方式,不是authorization-mode授权那个。是第一层的认证。
--anonymous-auth                  # 匿名访问,默认就是true。在没有被这层的其他认证方式拒绝的情况下就是匿名访问,比如在请求中证书或者是token都没有提供。 匿名访问拥有用户`system:anonymous`和组`system:unauthenticated`,给匿名访问授权就通过这俩。 
--authentication-token-webhook-config-file  # 通过远程服务器认证
--authentication-token-webhook-cache-ttl  # 对身份认证决定的缓存时间,默认2分钟。
--client-ca-file                  # 用来认证客户端的ca证书。
--requestheader-client-ca-file    # 用来认证客户端的ca证书, 认证通过以后,还要查看客户端的common name 是否包含在requestheader-allowed-names指定的列表里。
--requestheader-allowed-names     # 与requestheader-client-ca-file一起提供认证。
--service-account-key-file        # 解密验证service account token 的,可以使用证书,最好生成一个秘钥对,这里指定公钥。  controller-manager那里指定私钥。

--enable-bootstrap-token-auth     # 使用bootstrap-token认证需要启用这个,注意:这个bootstrap-token认证只是一种认证方式,不是启用bootstrap方式获取证书。他是只用于获取证书过程中的一种认证方式,但是获取证书的认证不是只有这一种,比如下面的--token-auth-file认证也可以。
--token-auth-file                 # 可以使用token文件认证。
# 上面的认证方式是'或'的关系, 只要有一种认证通过就行。
# (--requestheader-client-ca-file AND --requestheader-allowed-names) OR --client-ca-file OR --service-account-key-file OR --token-auth-file


# 授权相关。
--authorization-mode              # 授权认证模式, 一般是: RBAC, Node
--authorization-webhook-config-file   # 通过远程服务器确认授权。


# 扩展api相关
--proxy-client-cert-file                     # apiserver连接别人的证书,用于连接扩展API。
--proxy-client-key-file

# 身份认证代理
--requestheader-extra-headers-prefix=X-Remote-Extra-   # 指定额外信息使用的HTTP头部名称。
--requestheader-group-headers=X-Remote-Group    # 指定存放用户组的http头部
--requestheader-username-headers=X-Remote-User   # 指定存放用户名的http头部。


生成一对密钥:
私钥:

openssl genrsa -out sa.key 2048  

公钥:

openssl rsa -in sa.key -pubout -out sa.pub

requestheader-client-ca-file, client-ca-file

--requestheader-client-ca-file 与 --client-ca-file的不同就是前者还要通过--requestheader-allowed-names。
一般情况下, --requestheader-client-ca-file与--requestheader-allowed-names用来认证扩展的api服务,
就是创建kind: APIService的服务,如 metrics-server就是这样的。
--client-ca-file 是认证一般用户的。
--requestheader-client-ca-file 与 --client-ca-file 需要使用不同的CA,因为他们的认证方式是这个样子的:
(--requestheader-client-ca-file and --requestheader-allowed-names) or --client-ca-file
如果使用相同的ca, 会导致--requestheader-client-ca-file认证通过, 然后就会去判断--requestheader-allowed-names。


apiserver访问kubelet相关的参数

在执行kubectl logs, kubectl exec之类的命令时,apiserver需要访问kubelet。 这时就不是apiserver来认证kubelet了, 而是kubelet来认证apiserver。

1、--kubelet-https:

apiserver是否访问kubelet的https端口。 kubelet有两个端口, 一个是https端口,需要认证。 一个是http端口,不需要认证,是只读端口。
https端口虽然需要认证,但是因为kubelet默认开启了匿名访问,并且鉴权部分是允许所有,所以apiserver也是可以请求kubelet的。

2、--kubelet-certificate-authority:

指定CA证书, 在apiserver连接kubelet时,用来验证kubelet的https端口证书。 默认情况下kubelet的https证书是自签证书,没有ca,这个参数也就用不了了。 只有在kubelet指定了证书,或者是自动签署的服务证书,拥有CA证书的情况下,才会考虑是否用这个来验证。验证我访问的kubelet确实是我要访问的。

这个参数与下面这俩参数没关系。

3、--kubelet-client-certificate、--kubelet-client-key:

apiserver请求kubelet时提供的证书。 在kubelet关闭匿名访问,并且打开了客户端证书认证的时候。 apiserver必须指定这俩参数,不然kubectl logs, kubectl exec 这类需要访问kubelet的请求就会失败。

具体的kubelet认证可以看这里:
https://www.yxingxing.net/archives/kubelet-20201216-authentication

enable-bootstrap-token-auth

--enable-bootstrap-token-auth: 启用bootstrap-token认证。 允许kubelet在引导时使用bootstrap-token认证。 专门用于kubelet引导启动时认证的。
是一种用于验证kubelet的更简单且更易于管理的方法,并且在启动kube-apiserver时不需要任何其他标志。需要创建secret资源。

kubelet自动从apiserver获取签署的TLS证书,kubelet需要--bootstreap-kubeconfig配置文件设置令牌,其中的user部分就可以使用bootstrap-token, 也可以使用--token-auth-file里的token认证。证书可能也可以, 没有试过。
因为bootstrap-token是专用于kubelet引导启动时认证的,而且还有过期时间,所以安全性也高。

启用以后,可以在kube-system命名空间创建bootstrap.kubernetes.io/token类型的secret来创建token。

还需要在kube-controller-manager里面注意--controllers参数(启用的控制器), 需要启用bootstrapsigner, 默认是启用所有的, 一般不用管。

TLS引导以及相关配置: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/

bootstrap令牌验证: https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/

从上面的网址中抄出来的权限设置方式:

bootstrap的token没有明显的user和group, 使用的是k8s内置的system:bootstrappers组和system:nodes组,所以给这两个组授权就可以了。

1、 授权kubelet创建CSR证书请求文件, 需要给system:bootstrappers组绑定k8s内置的system:node-bootstrapper 角色。

2、 设置CSR是可以签署的, 需要给system:bootstrappers组绑定k8s内置的system:certificates.k8s.io:certificatesigningrequests:nodeclient 角色。

3、 授权kubelet能够自动续订证书, 需要给system:nodes组绑定k8s内置的system:certificates.k8s.io:certificatesigningrequests:selfnodeclient角色.

这种自动获取证书的方式,也不仅仅只有bootstrap令牌, 也可以用其他的验证方式,如serviceaccount token, 如统一的证书, 只要权限设置正确,kubelete的bootstrp-kubeconfig设置好就可以用了。

匿名访问

anonymous-auth

这个参数默认是启用的,--anonymous-auth=false可以关闭。
在其它的认证方式都没有拒绝的情况下,就是匿名访问。
给匿名访问授权通过用户system:anonymous和组system:unauthenticated.
如:
我这里开启的认证只有证书, 不提供证书,也就不会被拒绝。就是匿名访问了。
只不过没有对services资源的访问权限。

[root@k8smaster1 bin]# curl --cacert /opt/kubernetes/cert/k8s/k8s_ca.pem https://192.168.1.221:6443/api/v1/services
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "services is forbidden: User \"system:anonymous\" cannot list resource \"services\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "services"
  },
  "code": 403
}[root@k8smaster1 bin]# 

给匿名组或者用户添加权限就可以, 我这里给组添加了内置的view角色,有获取一些资源的权限。

[root@k8smaster1 bin]# kubectl create clusterrolebinding anonymous-view --clusterrole=view --group=system:unauthenticated
clusterrolebinding.rbac.authorization.k8s.io/anonymous-view created

再执行curl就有东西了, 列出的是刚建立集群就存在的servicekubernetes

[root@k8smaster1 bin]# curl --cacert /opt/kubernetes/cert/k8s/k8s_ca.pem https://192.168.1.221:6443/api/v1/services
{
  "kind": "ServiceList",
  "apiVersion": "v1",
  "metadata": {
    "selfLink": "/api/v1/services",
    "resourceVersion": "70562"
  },
  "items": [
    {
      "metadata": {
        "name": "kubernetes",
        "namespace": "default",
        "selfLink": "/api/v1/namespaces/default/services/kubernetes",
        "uid": "1d0edcb5-80d1-433d-9f0f-4f2b5faae6b5",
        "resourceVersion": "162",
        "creationTimestamp": "2020-12-13T11:21:12Z",
        "labels": {
          "component": "apiserver",
          "provider": "kubernetes"
        },
        "managedFields": [
          {
            "manager": "kube-apiserver",
            "operation": "Update",
            "apiVersion": "v1",
            "time": "2020-12-13T11:21:12Z",
            "fieldsType": "FieldsV1",
            "fieldsV1": {"f:metadata":{"f:labels":{".":{},"f:component":{},"f:provider":{}}},"f:spec":{"f:clusterIP":{},"f:ports":{".":{},"k:{\"port\":443,\"protocol\":\"TCP\"}":{".":{},"f:name":{},"f:port":{},"f:protocol":{},"f:targetPort":{}}},"f:sessionAffinity":{},"f:type":{}}}
          }
        ]
      },
      "spec": {
        "ports": [
          {
            "name": "https",
            "protocol": "TCP",
            "port": 443,
            "targetPort": 6443
          }
        ],
        "clusterIP": "10.0.0.1",
        "type": "ClusterIP",
        "sessionAffinity": "None"
      },
      "status": {
        "loadBalancer": {
          
        }
      }
    }
  ]
}[root@k8smaster1 bin]# 

关闭匿名访问以后:

[root@k8smaster1 controller]# curl --cacert /opt/kubernetes/cert/k8s/k8s_ca.pem https://192.168.1.221:6443/api/v1/services
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}[root@k8smaster1 controller]# 

参数配置

测试环境:

[Unit]
Description=kubernetes api server
After=network-online.target

[Service]
ExecStart=/opt/kubernetes/bin/kube-apiserver \
--log-dir=/opt/kubernetes/log/apiserver \
--logtostderr=false \
--v=4 \
--etcd-cafile=/opt/kubernetes/cert/etcd/etcd-ca.pem \
--etcd-certfile=/opt/kubernetes/cert/etcd/kube-apiserver-etcd-client.crt \
--etcd-keyfile=/opt/kubernetes/cert/etcd/kube-apiserver-etcd-client.key \
--etcd-servers=https://172.100.101.171:2379,https://172.100.101.172:2379,https://172.100.101.173:2379 \
--tls-cert-file=/opt/kubernetes/cert/k8s/kube-apiserver.crt \
--tls-private-key-file=/opt/kubernetes/cert/k8s/kube-apiserver.key \
--proxy-client-cert-file=/opt/kubernetes/cert/front-proxy/front-proxy-client.crt \
--proxy-client-key-file=/opt/kubernetes/cert/front-proxy/front-proxy-client.key \
--requestheader-client-ca-file=/opt/kubernetes/cert/front-proxy/front-proxy-ca.pem \
--requestheader-allowed-names=front-proxy-client \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--enable-bootstrap-token-auth \
--authorization-mode=RBAC,Node \
--client-ca-file=/opt/kubernetes/cert/k8s/kubernetes-ca.pem \
--service-account-key-file=/opt/kubernetes/cert/k8s/sa.pub \
--allow-privileged \
--service-cluster-ip-range=10.0.0.0/16 \
--kubelet-client-certificate=/opt/kubernetes/cert/k8s/kube-apiserver-kubelet-client.crt \
--kubelet-client-key=/opt/kubernetes/cert/k8s/kube-apiserver-kubelet-client.key \
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction,AlwaysPullImages \
--service-node-port-range=20000-50000


Restart=on-failure

[Install]
WantedBy=multi-user.target