2041 kube-apiserver

kube-apiserver既然为kubernetes中master的核心组件,并且是cluster中所有请求的终点,那么kubernetes是如何接收请求,又是如何将结果返回至客户端?

部署策略:

  • 3个节点高可用, 使用负载均衡或者haproxy/nginx 等4层透明代理实现高可用;

  • 关闭非安全端口 8080 和匿名访问;

  • 在安全端口 6443 接收 https 请求;

  • 严格的认证和授权策略 (x509、token、RBAC);

  • 开启 bootstrap token 认证,支持 kubelet TLS bootstrapping;

  • 使用 https 访问 kubelet、etcd,加密通信;

部署软件规划

IP

部署软件包

10.40.61.116

kube-apiserver

10.40.58.153

kube-apiserver

10.40.58.154

kube-apiserver

01.创建 kubernetes-master 证书和私钥

API Server证书主要用于客户端程序连接apiserver时进行加密和验证。Kubernetes API Server 凭证中必需包含 master 的静态 IP 地址。

创建 Kubernetes API Server 凭证签发请求文件:

cat > kube-apiserver-csr.json <<EOF
{
  "CN": "kubernetes",
  "hosts": [
    "10.40.61.116",
    "10.40.58.153",
    "10.40.58.154",
    "127.0.0.1",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local",
    "apiserver-p001.svc.gxd88.cn"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes",
      "ST": "Beijing"
    }
  ]
}
EOF

hosts 字段指定授权使用该证书的 IP 和域名列表,这里列出了 master 节点 IP、kubernetes 服务的 IP 和域名; kubernetes 服务 IP 是 apiserver 自动创建的,一般是 --service-cluster-ip-range 参数指定的网段的第一个IP

创建 Kubernetes API Server 凭证与私钥:

cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes \
  kube-apiserver-csr.json | cfssljson -bare kube-apiserver

结果产生以下两个文件:

kube-apiserver-key.pem
kube-apiserver.pem

02.Service Account 证书

Service Account证书用于生成各个Namespace默认的token,以及进行token验证。在集群内部服务访问API Server时会使用这个token进行身份认证,

其中kube-apiserver使用公钥, kube-controller-manager使用私钥

cat > service-account-csr.json <<EOF
{
  "CN": "service-accounts",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "China",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes",
      "ST": "Beijing"
    }
  ]
}
EOF

创建 Kubernetes service-account 凭证与私钥:

cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes \
  service-account-csr.json | cfssljson -bare service-account

结果将生成以下两个文件

service-account-key.pem
service-account.pem

03.使用systemd管理kube-apiserver

tee > /etc/systemd/system/kube-apiserver.service <<EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target


[Service]
ExecStart=/srv/kubernetes/bin/kube-apiserver \\
  --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,NodeRestriction \\
  --bind-address=0.0.0.0 \\
  --authorization-mode=Node,RBAC \\
  --enable-bootstrap-token-auth \\
  --token-auth-file=/srv/kubernetes/pki/bootstrap-token.csv \\
  --runtime-config=rbac.authorization.k8s.io/v1 \\
  --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \\
  --kubelet-https=true \\
  --kubelet-client-certificate=/srv/kubernetes/pki/kube-apiserver.pem \\
  --kubelet-client-key=/srv/kubernetes/pki/kube-apiserver-key.pem \\
  --anonymous-auth=false \\
  --requestheader-client-ca-file=/srv/kubernetes/pki/ca.pem \\
  --requestheader-allowed-names= \\
  --requestheader-extra-headers-prefix=X-Remote-Extra- \\
  --requestheader-group-headers=X-Remote-Group \\
  --requestheader-username-headers=X-Remote-User \\
  --proxy-client-cert-file=/srv/kubernetes/pki/admin.pem \\
  --proxy-client-key-file=/srv/kubernetes/pki/admin-key.pem \\
  --service-cluster-ip-range=10.244.0.0/16 \\
  --service-node-port-range=20000-45000 \\
  --tls-cert-file=/srv/kubernetes/pki/kube-apiserver.pem \\
  --tls-private-key-file=/srv/kubernetes/pki/kube-apiserver-key.pem \\
  --client-ca-file=/srv/kubernetes/pki/ca.pem \\
  --enable-aggregator-routing=true \\
  --service-account-key-file=/srv/kubernetes/pki/service-account.pem \\
  --etcd-cafile=/srv/kubernetes/pki/ca.pem \\
  --etcd-certfile=/srv/kubernetes/pki/etcd.pem \\
  --etcd-keyfile=/srv/kubernetes/pki/etcd-key.pem \\
  --etcd-servers=https://10.40.61.116:2379,https://10.40.58.153:2379,https://10.40.58.154:2379 \\
  --allow-privileged=true \\
  --audit-log-maxage=30 \\
  --audit-log-maxbackup=3 \\
  --audit-log-maxsize=100 \\
  --audit-log-path=/srv/kubernetes/log/api-audit.log \\
  --event-ttl=1h \\
  --v=2 \\
  --logtostderr=false \\
  --log-dir=/srv/kubernetes/log

Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

EOF

04.启动/停止 kube-apiserver

To configure kube-apiserver to start automatically when the system boots up, run the following commands:

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable kube-apiserver.service

kube-apiserver can be started and stopped as follows:

sudo systemctl start kube-apiserver.service
sudo systemctl stop kube-apiserver.service

05.验证

检查kube-apiserver服务:

 $ systemctl status kube-apiserver |grep Active
   Active: active (running) since 四 2020-04-16 13:44:33 CST; 2 days ago

查看kube-apiserver写入etcd的数据:

 /srv/kubernetes/bin/etcdctl \
    --endpoints=https://10.40.58.153:2379,https://10.40.58.154:2379,https://10.40.61.116:2379 \
    --cacert=/srv/kubernetes/pki/ca.pem \
    --cert=/srv/kubernetes/pki/etcd.pem \
    --key=/srv/kubernetes/pki/etcd-key.pem get /  --prefix --keys-only

检查集群信息

$ kubectl cluster-info
$ kubectl get all --all-namespaces
$ kubectl get componentstatuses

06.参数详解

kube-apiserver的参数,主要包括:

  • 准入插件

  • 扩展apiserver

  • 认证方式

  • 审计

  • 日志

  • etcd配置

  • 各种证书

  • 外部认证

  • ......

必须参数

/srv/kubernetes/bin/kube-apiserver \
    --service-cluster-ip-range=10.223.0.0/16 \
    --etcd-servers=https://etcd-1:2379,https://etcd-2:2379,https://etcd-3:2379

--service-cluster-ip-range: CIDR 表示的 IP 范围,服务的 cluster ip 将从中分配。 一定不要和分配给 nodes 和 pods 的 IP 范围产生重叠。

--etcd-servers: 连接的 etcd 服务器列表 , 形式为(scheme://ip:port),使用逗号分隔。

准入插件

比如开启PodPreset

/srv/kubernetes/bin/kube-apiserver \
    --enable-admission-plugins

apiserver租约

apiserver使用租约上网方式进行注册,能够感知上下线

/srv/kubernetes/bin/kube-apiserver \
    --endpoint-reconciler-type=lease

认证方式

节点使用Node,其他使用RBAC,某些组件可能会用到Webhook

/srv/kubernetes/bin/kube-apiserver \
    --authorization-mode=Node,RBAC

证书相关

/srv/kubernetes/bin/kube-apiserver \
    --tls-cert-file=/srv/kubernetes/pki/apiserver.pem \
  --tls-private-key-file=/srv/kubernetes/pki/apiserver-key.pem \
  --client-ca-file=/srv/kubernetes/pki/ca.pem \
  --service-account-key-file=/srv/kubernetes/pki/service-account.pem

--tls-cert-file: 包含用于 HTTPS 的默认 x509 证书的文件。(如果有 CA 证书,则附加于 server 证书之后)。如果启用了 HTTPS 服务,并且没有提供 --tls-cert-file 和 --tls-private-key-file,则将为公共地址生成一个自签名的证书和密钥并保存于 /var/run/kubernetes 目录。

--tls-private-key-file: 包含匹配 --tls-cert-file 的 x509 证书私钥的文件。

--client-ca-file: 如果设置此标志,对于任何请求,如果存包含 client-ca-file 中的 authorities 签名的客户端证书,将会使用客户端证书中的 CommonName 对应的身份进行认证。 所有的客户端证书由该CA进行签发

--service-account-key-file: 包含 PEM 加密的 x509 RSA 或 ECDSA 私钥或公钥的文件,用于验证 ServiceAccount 令牌。如果设置该值,--tls-private-key-file 将会被使用。指定的文件可以包含多个密钥,并且这个标志可以和不同的文件一起多次使用。

kubelet 接入配置

/srv/kubernetes/bin/kube-apiserver \
    --kubelet-https=true \
  --kubelet-client-certificate=/srv/kubernetes/pki/apiserver.pem \
  --kubelet-client-key=/srv/kubernetes/pki/apiserver-key.pem

--kubelet-client-certificate: 用于 TLS 的客户端证书文件路径。

--kubelet-client-key: 用于 TLS 的客户端证书密钥文件路径 .

--kubelet-https:为 kubelet 启用 https。 (默认值 true)

这个里面配置的证书是kube-apiserver访问kubelet时使用

设置API访问审计日志

开启k8s的审计功能,必须配置--audit-policy-file才会生效。

/srv/kubernetes/bin/kube-apiserver \
  --audit-log-maxage=30 \
  --audit-log-maxbackup=3 \
  --audit-log-maxsize=100 \
  --audit-log-path=/srv/kubernetes/log/api-audit.log \
  --audit-policy-file=/srv/kubernetes/conf/audit-policy-minimal.yml

--audit-log-path: 如果设置该值,所有到apiserver 的请求都将会被记录到这个文件。'-' 表示记录到标准输出。

--audit-log-maxage: 基于文件名中的时间戳,旧审计日志文件的最长保留天数

--audit-log-maxbackup: 旧审计日志文件的最大保留个数

--audit-log-maxsize: 审计日志被轮转前的最大兆字节数。

--audit-policy-file: 定义审计策略配置的文件的路径。需要打开 AdvancedAuditing'特性开关。AdvancedAuditing 需要一个配置来启用审计功能。

程序运行日志

/srv/kubernetes/bin/kube-apiserver \
  --v=2 \
  --logtostderr=false \
  --log-dir=/srv/kubernetes/log

设置ETCD证书信息

/srv/kubernetes/bin/kube-apiserver \
  --etcd-cafile=/srv/kubernetes/pki/ca.pem \
  --etcd-certfile=/srv/kubernetes/pki/apiserver.pem \
  --etcd-keyfile=/srv/kubernetes/pki/apiserver-key.pem \
  --etcd-servers=https://etcd-1:2379,https://etcd-2:2379,https://etcd-3:2379

--etcd-cafile: 用于保护 etcd 通信的 SSL CA 文件。

--etcd-certfile: 用于保护 etcd 通信的的 SSL 证书文件。

--etcd-keyfile: 用于保护 etcd 通信的 SSL 密钥文件。

--etcd-servers: 连接的 etcd 服务器列表 , 形式为(scheme://ip:port),使用逗号分隔。

开启扩展apiserver

开启扩展apiserver,比如metrics-server,再比如prometheus-adapter

/srv/kubernetes/bin/kube-apiserver \
  --requestheader-client-ca-file=/srv/kubernetes/pki/ca.pem
  --requestheader-allowed-names=
  --requestheader-extra-headers-prefix=X-Remote-Extra-
  --requestheader-group-headers=X-Remote-Group
  --requestheader-username-headers=X-Remote-User
  --proxy-client-cert-file=/srv/kubernetes/pki/admin.pem
  --proxy-client-key-file=/srv/kubernetes/pki/admin-key.pem

--requestheader-allowed-names: 使用 --requestheader-username-headers 指定的,允许在头部提供用户名的客户端证书通用名称列表。如果为空,任何通过 --requestheader-client-ca-file 中 authorities 验证的客户端证书都是被允许的。

--requestheader-client-ca-file: 在信任请求头中以 --requestheader-username-headers 指示的用户名之前,用于验证接入请求中客户端证书的根证书捆绑。

--requestheader-extra-headers-prefix: 用于检查的请求头的前缀列表。建议使用 X-Remote-Extra-。

--requestheader-group-headers: 用于检查群组的请求头列表。建议使用 X-Remote-Group.

--requestheader-username-headers : 用于检查用户名的请求头列表。建议使用 X-Remote-User。

--proxy-client-cert-file: 当必须调用外部程序时,用于证明 aggregator 或者 kube-apiserver 的身份的客户端证书。包括代理到用户 api-server 的请求和调用 webhook 准入控制插件的请求。它期望这个证书包含一个来自于 CA 中的 --requestheader-client-ca-file 标记的签名。该 CA 在 kube-system 命名空间的 'extension-apiserver-authentication' configmap 中发布。从 Kube-aggregator 收到调用的组件应该使用该 CA 进行他们部分的双向 TLS 验证。

--proxy-client-key-file: 当必须调用外部程序时,用于证明 aggregator 或者 kube-apiserver 的身份的客户端证书密钥。包括代理到用户 api-server 的请求和调用 webhook 准入控制插件的请求。

支持节点以bootstrap-token加入集群

/srv/kubernetes/bin/kube-apiserver \
  --enable-bootstrap-token-auth
  --token-auth-file=/srv/kubernetes/pki/bootstrap-token.csv

--enable-bootstrap-token-auth: 启用此选项以允许 kube-system 命名空间中的bootstrap.kubernetes.io/token'类型密钥可以被用于 TLS 的启动认证

--token-auth-file: 如果设置该值,这个文件将被用于通过令牌认证来保护 API 服务的安全端口。

开放某些api组支持

/srv/kubernetes/bin/kube-apiserver \
  --runtime-config=rbac.authorization.k8s.io/v1=true
  --runtime-config=rbac.authorization.k8s.io/v1beta1=true
  --runtime-config=settings.k8s.io/v1alpha1=true

比如podpreset需要--runtime-config=settings.k8s.io/v1alpha1=true,再比如custom metrics需要--runtime-config=rbac.authorization.k8s.io/v1beta1=true

service的虚拟IP,也就是ClusterIP网段

/srv/kubernetes/bin/kube-apiserver \
    --service-cluster-ip-range=10.223.0.0/16

NodePort的端口范围

/srv/kubernetes/bin/kube-apiserver \
    --service-node-port-range=20000-45000

最后更新于