4、K8S 证书说明

1、K8S 证书列表说明 https://www.jianshu.com/p/549ab7a059b0

1.1、How certificates are used by your cluster

Kubernetes requires PKI for the following operations:
  • Client certificates for the kubelet to authenticate to the API server
  • Server certificate for the API server endpoint
  • Client certificates for administrators of the cluster to authenticate to the API server
  • Client certificates for the API server to talk to the kubelets
  • Client certificate for the API server to talk to etcd
  • Client certificate/kubeconfig for the controller manager to talk to the API server
  • Client certificate/kubeconfig for the scheduler to talk to the API server.
  • Client and server certificates for the front-proxy
  • API server端点的服务器证书
    用于群集管理员向API服务器进行身份验证的客户端证书

  • API服务器与kubelets对话的客户端证书
    API服务器与etcd对话的客户端证书
  • kubelet的客户端证书以向API服务器进行身份验证
    客户端证书/kubeconfig  以使controller manager与API服务器对话
    客户端证书/kubeconfig  以使scheduler与API服务器对话的。
  • front-proxy的客户端和服务器证书
Note: front-proxy certificates are required only if you run kube-proxy to support an extension API server.
仅当您运行kube-proxy以支持扩展API服务器时,才需要front-proxy证书。

etcd also implements mutual TLS to authenticate clients and peers.

etcd还实现了双向TLS来对客户端和对等方进行身份验证。

1.2、Where certificates are stored存储证书的位置

If you install Kubernetes with kubeadm, certificates are stored in /etc/kubernetes/pki. All paths in this documentation are relative to that directory.

1.3、Configure certificates manually手动配置证书

If you don't want kubeadm to generate the required certificates, you can create them in either of the following ways.

Single root CA

You can create a single root CA, controlled by an administrator. This root CA can then create multiple intermediate CAs, and delegate all further creation to Kubernetes itself.

您可以创建由管理员控制的单个根CA。然后,该根CA可以创建多个中间CA,并将所有进一步的创建委托给Kubernetes本身。

Required CAs:

pathDefault CNdescription
ca.crt,key kubernetes-ca Kubernetes general CA
etcd/ca.crt,key etcd-ca For all etcd-related functions
front-proxy-ca.crt,key kubernetes-front-proxy-ca For the front-end proxy

On top of the above CAs, it is also necessary to get a public/private key pair for service account management, sa.key and sa.pub.

除了上述CA之外,还必须获得用于service account管理的公共/私有密钥对sa.key和sa.pub。

All certificates

If you don't wish to copy the CA private keys to your cluster, you can generate all certificates yourself.

Required certificates:

Default CNParent CAO (in Subject)kindhosts (SAN)
kube-etcd etcd-ca   server, client localhost127.0.0.1
kube-etcd-peer etcd-ca   server, client <hostname><Host_IP>localhost127.0.0.1
kube-etcd-healthcheck-client etcd-ca   client  
kube-apiserver-etcd-client etcd-ca system:masters client  
kube-apiserver kubernetes-ca   server <hostname><Host_IP><advertise_IP>[1]
kube-apiserver-kubelet-client kubernetes-ca system:masters client  
front-proxy-client kubernetes-front-proxy-ca   client  

[1]: any other IP or DNS name you contact your cluster on (as used by kubeadm the load balancer stable IP and/or DNS name, kuberneteskubernetes.defaultkubernetes.default.svckubernetes.default.svc.clusterkubernetes.default.svc.cluster.local)

where kind maps to one or more of the x509 key usage types:

kindKey usage
server digital signature, key encipherment, server auth
client digital signature, key encipherment, client auth
Note: Hosts/SAN listed above are the recommended ones for getting a working cluster; if required by a specific setup, it is possible to add additional SANs on all the server certificates.
Note:

For kubeadm users only:

  • The scenario where you are copying to your cluster CA certificates without private keys is referred as external CA in the kubeadm documentation.
  • If you are comparing the above list with a kubeadm generated PKI, please be aware that kube-etcdkube-etcd-peer and kube-etcd-healthcheck-client certificates are not generated in case of external etcd.

Certificate paths

Certificates should be placed in a recommended path (as used by kubeadm). Paths should be specified using the given argument regardless of location.

Default CNrecommended key pathrecommended cert pathcommandkey argumentcert argument
etcd-ca etcd/ca.key etcd/ca.crt kube-apiserver   --etcd-cafile
kube-apiserver-etcd-client apiserver-etcd-client.key apiserver-etcd-client.crt kube-apiserver --etcd-keyfile --etcd-certfile
kubernetes-ca ca.key ca.crt kube-apiserver   --client-ca-file
kubernetes-ca ca.key ca.crt kube-controller-manager --cluster-signing-key-file --client-ca-file, --root-ca-file, --cluster-signing-cert-file
kube-apiserver apiserver.key apiserver.crt kube-apiserver --tls-private-key-file --tls-cert-file
kube-apiserver-kubelet-client apiserver-kubelet-client.key apiserver-kubelet-client.crt kube-apiserver --kubelet-client-key --kubelet-client-certificate
front-proxy-ca front-proxy-ca.key front-proxy-ca.crt kube-apiserver   --requestheader-client-ca-file
front-proxy-ca front-proxy-ca.key front-proxy-ca.crt kube-controller-manager   --requestheader-client-ca-file
front-proxy-client front-proxy-client.key front-proxy-client.crt kube-apiserver --proxy-client-key-file --proxy-client-cert-file
etcd-ca etcd/ca.key etcd/ca.crt etcd   --trusted-ca-file, --peer-trusted-ca-file
kube-etcd etcd/server.key etcd/server.crt etcd --key-file --cert-file
kube-etcd-peer etcd/peer.key etcd/peer.crt etcd --peer-key-file --peer-cert-file
etcd-ca   etcd/ca.crt etcdctl   --cacert
kube-etcd-healthcheck-client etcd/healthcheck-client.key etcd/healthcheck-client.crt etcdctl --key --cert

Same considerations apply for the service account key pair:

private key pathpublic key pathcommandargument
sa.key   kube-controller-manager --service-account-private-key-file
  sa.pub kube-apiserver --service-account-key-file

1.4、Configure certificates for user accounts配置用户帐户的证书

You must manually configure these administrator account and service accounts:

filenamecredential nameDefault CNO (in Subject)
admin.conf default-admin kubernetes-admin system:masters
kubelet.conf default-auth system:node:<nodeName> (see note) system:nodes
controller-manager.conf default-controller-manager system:kube-controller-manager  
scheduler.conf default-scheduler system:kube-scheduler  
Note: The value of <nodeName> for kubelet.conf must match precisely the value of the node name provided by the kubelet as it registers with the apiserver. For further details, read the Node Authorization.
  1. For each config, generate an x509 cert/key pair with the given CN and O.

  2. Run kubectl as follows for each config:

KUBECONFIG=<filename> kubectl config set-cluster default-cluster --server=https://<host ip>:6443 --certificate-authority <path-to-kubernetes-ca> --embed-certs
KUBECONFIG=<filename> kubectl config set-credentials <credential-name> --client-key <path-to-key>.pem --client-certificate <path-to-cert>.pem --embed-certs
KUBECONFIG=<filename> kubectl config set-context default-system --cluster default-cluster --user <credential-name>
KUBECONFIG=<filename> kubectl config use-context default-system

These files are used as follows:

filenamecommandcomment
admin.conf kubectl Configures administrator user for the cluster
kubelet.conf kubelet One required for each node in the cluster.
controller-manager.conf kube-controller-manager Must be added to manifest in manifests/kube-controller-manager.yaml
scheduler.conf kube-scheduler Must be added to manifest in manifests/kube-scheduler.yaml

 

 2、配置聚合层允许kubernetes apiserver使用其他api进行扩展,这些api不是核心kubernetesapi的一部分。

要使聚合层在您的环境中正常运行以支持代理服务器和扩展apiserver之间的相互TLS身份验证,需要满足一些设置要求

Kubernetes和kube-apiserver具有多个CA,因此请确保代理是由聚合层CA签名的,而不是由主CA签名的。

认证流程:

与自定义资源定义(CRD)不同,聚合API除了标准的Kubernetes apiserver之外,还涉及另一台服务器-您的扩展apiserver,Kubernetes apiserver将需要与您的扩展apiserver通信,并且您的扩展apiserver将需要与Kubernetes apiserver通信,为了确保此通信的安全,Kubernetes apiserver使用x509证书向扩展apiserver进行身份验证。

本节介绍身份验证和授权流的工作方式以及如何配置它们。

Kubernetes apiserver:对发出请求的用户进行身份验证,并授权其对请求的API路径的权限。
Kubernetes apiserver:将请求代理到扩展apiserver
扩展apiserver:验证来自Kubernetes apiserver的请求
扩展apiserver:授权来自原始用户的请求
扩展apiserver:执行

2.1、本节的其余部分详细描述了这些步骤。该流程可以在下图中看到。

1、Kubernetes Apiserver Authentication and Authorization 

对扩展apiserver提供的API路径的请求与所有API请求的开始方式相同:与Kubernetes apiserver通信。此路径已由扩展apiserver向Kubernetes apiserver注册。

用户与Kubernetes apiserver通信,请求访问路径。 Kubernetes apiserver使用通过Kubernetes apiserver配置的标准身份验证和授权来验证用户并授权对特定路径的访问。

For an overview of authenticating to a Kubernetes cluster, see "Authenticating to a Cluster"认证. For an overview of authorization of access to Kubernetes cluster resources, see "Authorization Overview"授权.

到目前为止,所有内容都是标准的Kubernetes API请求,身份验证和授权。
Kubernetes apiserver现在准备将请求发送到扩展apiserver

2、Kubernetes Apiserver Proxies the Request

Kubernetes apiserver现在将向注册处理此请求的扩展apiserver发送或代理请求。为此,它需要知道以下几点:

2.1、Kubernetes apiserver应该如何向扩展apiserver进行身份验证,以通知扩展apiserver通过网络发出的请求来自有效的Kubernetes apiserver?

2.2、Kubernetes apiserver应该如何向扩展apiserver通知对其原始请求进行身份验证的用户名和组?

为了提供这两个,您必须使用多个标志配置Kubernetes apiserver

3、Kubernetes Apiserver Client Authentication

Kubernetes apiserver通过TLS连接到扩展apiserver,并使用客户端证书进行身份验证。您必须在启动时使用提供的标志向Kubernetes apiserver提供以下内容:

  • private key file via --proxy-client-key-file
  • signed client certificate file via --proxy-client-cert-file
  • certificate of the CA that signed the client certificate file via --requestheader-client-ca-file
  • valid Common Name values (CNs) in the signed client certificate via --requestheader-allowed-names

Kubernetes apiserver将使用--proxy-client-*-file指示的文件对扩展apiserver进行身份验证。为了使兼容扩展apiserver将该请求视为有效,必须满足以下条件:

  • 必须使用由CA签名的客户端证书建立连接,该ca的证书位于--requestheader-client-ca-file中
  • 必须使用其CN是--requestheader allowed names中列出的内容之一的客户端证书建立连接

注意:您可以将此选项设置为空白,即--requestheader-allowed-names =“”。这将向扩展apiserver指示任何CN都是可接受的。

使用这些选项启动时,Kubernetes apiserver将:

  • 使用它们对扩展服务器进行身份验证。
  • 在kube-system命名空间中创建一个名为extension apiserver authentication的configmap,它将在其中放置CA证书和允许的CNs。反过来,扩展服务器可以检索这些信息来验证请求。

请注意,Kubernetes apiserver使用相同的客户端证书对所有扩展apiserver进行身份验证。它不会为每个扩展apiserver创建一个客户机证书,而是创建一个作为Kubernetes apiserver进行身份验证的证书。对于所有扩展apiserver请求,都会重用同一个。

4、Original Request Username and Group

当Kubernetes apiserver将请求代理到扩展apiserver时,它将通知扩展apiserver用户名和组,原始请求已成功通过该用户名和组进行了身份验证

它在其代理请求的http标头中提供了这些信息。您必须将要使用的标头名称告知Kubernetes apiserver。

  • the header in which to store the username via --requestheader-username-headers
  • the header in which to store the group via --requestheader-group-headers
  • the prefix to append to all extra headers via --requestheader-extra-headers-prefix

些标头名称也放置在extension-apiserver-authentication configmap中,因此扩展apiserver可以检索和使用它们

5、Extension Apiserver Authenticates the Request

扩展apiserver在收到来自Kubernetes apiserver的代理请求后,必须验证该请求确实确实来自有效的身份验证代理,该身份验证代理由Kubernetes apiserver履行。扩展apiserver通过以下方式对其进行验证:

如上所述,从kube-system的configmap中检索以下内容:

  • 客户端CA证书
  • 允许的名称(CN)列表
  • 用户名,组和其他信息的标头名称

使用以下客户端证书检查TLS连接是否已通过身份验证:

  • 由其证书与检索到的CA证书匹配的CA签名。
  • 在允许的CN列表中有一个CN,除非列表为空(在这种情况下,所有CN都被允许)。
  • 从相应的标头中提取用户名和组

Was signed by the CA whose certificate matches the retrieved CA certificate.

如果上述过程通过,则该请求是来自合法身份验证代理(在本例中是Kubernetes apiserver)的有效代理请求。

请注意,扩展apiserver实现负责提供上述功能。许多默认情况下是这样做的,利用k8s.io/apiserver/包。其他人可以使用命令行选项提供覆盖它的选项。

 为了获得检索configmap的权限,扩展服务器需要相应的角色。kube-system命名空间中有一个名为extension apiserver authentication reader的默认角色,可以分配该角色

 

 

 --requestheader-allowed-names=front-proxy-client对应cm如下

kubectl get cm extension-apiserver-authentication -n kube-system -oyaml
apiVersion: v1
data:
  client-ca-file: |
    -----BEGIN CERTIFICATE-----
    MIIDejCCAmKgAwIBAgIUbqgbnLVub4spN2jKLNcn9wT+VXQwDQYJKoZIhvcNAQEL
    BQAwQzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0Jl
    aWppbmcxEDAOBgNVBAMTB2V0Y2QgQ0EwHhcNMjAxMjMwMDc0OTAwWhcNMjUxMjI5
    MDc0OTAwWjBDMQswCQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UE
    BxMHQmVpamluZzEQMA4GA1UEAxMHZXRjZCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
    ggEPADCCAQoCggEBAJ5c6J1jLowz/Q8gel4jut6vO4s8MAnvgViIlNXAyGoRo7R/
    n8sxaYN/ts5yHX7CU49ZhUOxd41MAuBfuUFd+kUR8kJ5otRpAe7QSQqJ4Kx2vjcG
    uqtFWFLc2Q1PR3751cAPjbeFwX0m1q8XXPwjig3UeQi1av37VeNW8iKqs9ZAQ8mW
    VQ42ceEwK8O6RzqH6YMFR6BEeE/22zlhMNrdlsQ9B7PBGs3jWlHljZ0LyryMMA9y
    Wi0RBzXhYXLp72VKliNKK2KuaUgQOuZGPF7aEIbdyo0ectX1J6c0UgZqIYS2HsEH
    I00xvUE/eTxluy8w/HOulsMJqPl5SWYxOwyE3Y0CAwEAAaNmMGQwDgYDVR0PAQH/
    BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFMmFz/coesIglm6G
    GvIGoz0gSCOQMB8GA1UdIwQYMBaAFMmFz/coesIglm6GGvIGoz0gSCOQMA0GCSqG
    SIb3DQEBCwUAA4IBAQAYA0Hu+C2EcuYqqp7Pdkv0w8JIF14SAbUUQUpqmeXnRfHV
    N9Va3zT1A2jQ5rSZupBL33S6SU+ayOpvLM+2334wJGE5tZTOYga79vyGuh/W1q1l
    K/RHFB/RfYKR+NOjFDi8o7GwtkO1jeegfrqXAW77aEP1Ndl6PUm95a+PsUUTgsit
    7fMn0OFgWCOq6DGucP3THalz7tFW+OR5cZZ1XLjkRVDSEGFRVrSWS+g5chmfkuzo
    4GJC4+bxdgjznAiavUlBCgIc0SjZmQTxqFqHdmZkmRcVD0zBiVQfwFzM+7EFrqBu
    2b9UqvBPfI8q04cqSbhxzQjq15OYNvII03g1YzFa
    -----END CERTIFICATE-----
  requestheader-allowed-names: '["aggregator","front-proxy-client"]'
  requestheader-client-ca-file: |
    -----BEGIN CERTIFICATE-----
    MIIDejCCAmKgAwIBAgIUbqgbnLVub4spN2jKLNcn9wT+VXQwDQYJKoZIhvcNAQEL
    BQAwQzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaWppbmcxEDAOBgNVBAcTB0Jl
    aWppbmcxEDAOBgNVBAMTB2V0Y2QgQ0EwHhcNMjAxMjMwMDc0OTAwWhcNMjUxMjI5
    MDc0OTAwWjBDMQswCQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UE
    BxMHQmVpamluZzEQMA4GA1UEAxMHZXRjZCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
    ggEPADCCAQoCggEBAJ5c6J1jLowz/Q8gel4jut6vO4s8MAnvgViIlNXAyGoRo7R/
    n8sxaYN/ts5yHX7CU49ZhUOxd41MAuBfuUFd+kUR8kJ5otRpAe7QSQqJ4Kx2vjcG
    uqtFWFLc2Q1PR3751cAPjbeFwX0m1q8XXPwjig3UeQi1av37VeNW8iKqs9ZAQ8mW
    VQ42ceEwK8O6RzqH6YMFR6BEeE/22zlhMNrdlsQ9B7PBGs3jWlHljZ0LyryMMA9y
    Wi0RBzXhYXLp72VKliNKK2KuaUgQOuZGPF7aEIbdyo0ectX1J6c0UgZqIYS2HsEH
    I00xvUE/eTxluy8w/HOulsMJqPl5SWYxOwyE3Y0CAwEAAaNmMGQwDgYDVR0PAQH/
    BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFMmFz/coesIglm6G
    GvIGoz0gSCOQMB8GA1UdIwQYMBaAFMmFz/coesIglm6GGvIGoz0gSCOQMA0GCSqG
    SIb3DQEBCwUAA4IBAQAYA0Hu+C2EcuYqqp7Pdkv0w8JIF14SAbUUQUpqmeXnRfHV
    N9Va3zT1A2jQ5rSZupBL33S6SU+ayOpvLM+2334wJGE5tZTOYga79vyGuh/W1q1l
    K/RHFB/RfYKR+NOjFDi8o7GwtkO1jeegfrqXAW77aEP1Ndl6PUm95a+PsUUTgsit
    7fMn0OFgWCOq6DGucP3THalz7tFW+OR5cZZ1XLjkRVDSEGFRVrSWS+g5chmfkuzo
    4GJC4+bxdgjznAiavUlBCgIc0SjZmQTxqFqHdmZkmRcVD0zBiVQfwFzM+7EFrqBu
    2b9UqvBPfI8q04cqSbhxzQjq15OYNvII03g1YzFa
    -----END CERTIFICATE-----
  requestheader-extra-headers-prefix: '["X-Remote-Extra-"]'
  requestheader-group-headers: '["X-Remote-Group"]'
  requestheader-username-headers: '["X-Remote-User"]'
kind: ConfigMap
metadata:
  creationTimestamp: "2020-12-30T14:43:46Z"
  name: extension-apiserver-authentication
  namespace: kube-system
  resourceVersion: "5063327"
  selfLink: /api/v1/namespaces/kube-system/configmaps/extension-apiserver-authentication
  uid: 49c22e94-880e-456a-b3df-c3c4c3e04e4d
View Code

 

# kubectl get role extension-apiserver-authentication-reader -n kube-system -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2020-12-30T14:43:56Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: extension-apiserver-authentication-reader
  namespace: kube-system
  resourceVersion: "136"
  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/kube-system/roles/extension-apiserver-authentication-reader
  uid: fd2bf774-3f0b-40b9-9108-24b9beeda0ac
rules:
- apiGroups:
  - ""
  resourceNames:
  - extension-apiserver-authentication
  resources:
  - configmaps
  verbs:
  - get
  - list
  - watch
View Code

6、Extension Apiserver Authorizes the Request 

扩展apiserver现在可以验证从头部检索到的用户/组是否有权执行给定的请求。它通过向Kubernetes apis服务器发送一个标准SubjectAccessReview请求来实现。

为了使扩展apiserver本身被授权可以将SubjectAccessReview请求提交给Kubernetes apiserver,它需要正确的权限。 Kubernetes包含一个默认的ClusterRole,名为system:auth-delegator,具有适当的权限。可以将其授予扩展apiserver的服务帐户。

kubectl get clusterrole system:auth-delegator -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2020-12-30T14:43:56Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:auth-delegator
  resourceVersion: "64"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/system%3Aauth-delegator
  uid: 9dd97ade-aa90-4080-b5ea-298c45a33bdc
rules:
- apiGroups:
  - authentication.k8s.io
  resources:
  - tokenreviews
  verbs:
  - create
- apiGroups:
  - authorization.k8s.io
  resources:
  - subjectaccessreviews
  verbs:
  - create
View Code

7、Extension Apiserver Executes

如果SubjectAccessReview通过,则扩展apiserver将执行请求。

 

启用Kubernetes Apiserver标志

通过以下kube-apiserver标志启用聚合层。

-requestheader-client-ca-file=<path to aggregator CA cert>
--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
--proxy-client-cert-file=<path to aggregator proxy cert>
--proxy-client-key-file=<path to aggregator proxy key>

2.2、 CA Reusage and Conflicts

Kubernetes apiserver有两个客户端CA选项:

  • --client-ca-file
  • --requestheader-client-ca-file

这些功能中的每一个都是独立的,如果使用不当,它们之间可能会发生冲突。

  • --client-ca-file: When a request arrives to the Kubernetes apiserver, if this option is enabled, the Kubernetes apiserver checks the certificate of the request. If it is signed by one of the CA certificates in the file referenced by --client-ca-file, then the request is treated as a legitimate request, and the user is the value of the common name CN=, while the group is the organization O=. See the documentation on TLS authentication.
    当请求到达Kubernetes apiserver时,如果启用此选项,Kubernetes apiserver将检查请求的证书。如果它是由--client CA file引用的文件中的某个CA证书签名的,则该请求将被视为合法请求,并且用户是公共名称CN=的值,而组是组织O=。请参阅有关TLS身份验证的文档。
    • 根据用户名具有的权限进行授权????????
       
  • --requestheader-client-ca-file: When a request arrives to the Kubernetes apiserver, if this option is enabled, the Kubernetes apiserver checks the certificate of the request. If it is signed by one of the CA certificates in the file reference by --requestheader-client-ca-file, then the request is treated as a potentially legitimate request. The Kubernetes apiserver then checks if the common name CN= is one of the names in the list provided by --requestheader-allowed-names. If the name is allowed, the request is approved; if it is not, the request is not.

  当请求到达Kubernetes apiserver时,如果启用此选项,Kubernetes apiserver将检查请求的证书。如果它是由--requestheader-client-ca-file文件引用中的一个CA证书签名的,那么该请求将被视为一个潜在的合法请求。然后Kubernetes apiserver检查公共名CN=是否是--requestheader allowed names提供的列表中的一个名称。如果名称允许,则请求被批准;如果不允许,则请求不被批准。

 

 

如果同时提供了--client-ca-file和--requestheader-client-ca-file,则请求首先检查--requestheader-client-ca-file CA,然后再检查--client-ca-file。通常,对于这些选项中的每一个,都使用不同的CA,即根CA或中间CA。常规客户端请求与--client-ca-file匹配,而聚合请求与--requestheader-client-ca-file匹配。但是,如果两个都使用相同的CA,则通常会通过--client-ca-file传递的客户端请求将失败,因为CA将匹配--requestheader-client-ca-file中的CA,但公共名称CN=将不匹配--requestheader-allowed-names允许名称中可接受的公共名称之一。这可能会导致kubelets和其他控制平面组件以及终端用户无法通过Kubernetes apis服务器的身份验证。

或出于这个原因,请使用不同的证书授权。--client-ca-file选项-授权控制平面组件和终端用     --requestheader-client-ca-file选项授权聚合apiserver请求。

警告:除非您了解保护CA使用的风险和机制,否则不要重用在不同上下文中使用的CA。

如果您没有在运行API服务器的主机上运行kube代理,则必须确保系统已启用以下kube apiserver标志:

--enable-aggregator-routing=true

2.3、Register APIService objects

您可以动态配置将哪些客户端请求代理到扩展apiserver。以下是注册示例:

apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: <name of the registration object>
spec:
  group: <API group name this extension apiserver hosts>
  version: <API version this extension apiserver hosts>
  groupPriorityMinimum: <priority this APIService for this group, see API documentation>
  versionPriority: <prioritizes ordering of this version within a group, see API documentation>
  service:
    namespace: <namespace of the extension apiserver service>
    name: <name of the extension apiserver service>
  caBundle: <pem encoded ca cert that signs the server cert used by the webhook>
View Code

2.4、Contacting the extension apiserver

一旦Kubernetes apiserver确定应将请求发送到扩展apiserver,它就需要知道如何联系它。

service字段是对扩展apiserver的服务的引用。服务命名空间和名称是必需的。端口是可选的,默认为443。

下面是一个扩展apiserver的示例,它被配置为在端口“1234”上调用,并根据ServerName  my-service-name.my-service-namespace.svc验证TLS连接。

apiVersion: apiregistration.k8s.io/v1
kind: APIService
...
spec:
  ...
  service:
    namespace: my-service-namespace
    name: my-service-name
    port: 1234
  caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
View Code

 

2.5、What's next 

 

3、Setup an extension api-server

设置扩展API服务器以与聚合层一起使用,可以使用其他API扩展Kubernetes apiserver,而这些API并不是核心Kubernetes API的一部分

下面的步骤描述如何在高层设置扩展服务器。无论您使用的是YAML配置还是api,这些步骤都适用。试图明确指出两者之间的任何差异。有关如何使用YAML配置实现它们的具体示例,可以查看Kubernetes repo中的示例apiserver。sample-apiserver或者,您可以使用现有的第三方解决方案,例如apiserver-builder,,它应该为您生成一个框架并自动执行以下所有步骤。

1、确保启用了apiservice api(检查--runtime config)。默认情况下,它应该是打开的,除非在集群中故意关闭它。
2、您可能需要制定一个允许您添加APIService对象的RBAC规则,或者让集群管理员制定一个规则。(由于API扩展会影响整个集群,因此不建议在活动集群中对API扩展进行测试/开发/调试。)
3、创建要在其中运行扩展api服务的Kubernetes命名空间。
4、创建/获取CA证书,用于对扩展api-server用于HTTPS的server cert进行签名。
5、为用于HTTPS的api-server创建server cert/key。此证书应由上述CA签名。它还应具有Kube DNS名称的CN。它派生自Kubernetes服务,其形式为<service name><service name namespace>.svc
6、使用命名空间中的server cert/key创建Kubernetes secret。
7、为扩展api-server创建Kubernetes部署,并确保将secret作为卷加载。它应该包含对扩展api-server的工作映像的引用。部署也应该在您的命名空间中。
8、请确保您的扩展服务器从该卷加载这些证书,并且在HTTPS握手中使用这些证书。
9、在命名空间中创建Kubernetes sa。
10、为您希望在资源上允许的操作创建Kubernete cluster role。
11、为命名空间中的sa创建Kubernetes cluster role binding,绑定到刚才创建的cluster role。
12、从命名空间中的sa创建Kubernetes cluster role binding到system:auth-delegator cluster role将身份验证决策委托给Kubernetes核心API服务器。
13、创建从命名空间中的sa与extension-apiserver-authentication-reader 的Kubernetes role binding。这允许扩展api服务器访问extension-apiserver-authentication configmap
14、创建Kubernetes apiservice。上面的CA证书应该是base64编码的,去掉新行并用作spec。不应使用名称空间。如果使用kube-aggregator API,,只传入PEM编码的CA包,因为base64编码已经为您完成。
15、使用kubectl获取资源。运行时,kubectl应该返回“No resources found”。此消息表示一切正常,您当前没有创建该资源类型的对象。

 

 

 

4、Extending the Kubernetes API with the aggregation layer

Aggregation layer

聚合层与kube apiserver一起运行。在注册扩展资源之前,聚合层将什么也不做。要注册一个API,需要添加一个APIService对象,该对象“声明”kubernetes api中的URL路径。此时,聚合层将代理发送该API路径的任何内容(例如/apis/myextension.mycompany.io/v1/…)到注册的APIService。

实施APIService的最常见方法是在集群中运行的Pod中运行扩展API服务器。如果您使用扩展API服务器来管理集群中的资源,则扩展API服务器(也称为“扩展-api服务器”)通常与一个或多个控制器配对。 apiserver-builder库为扩展API服务器和关联的控制器提供了框架。
Response latency

扩展API服务器应该与kube apis服务器之间具有低延迟的网络连接。发现请求需要在5秒或更短的时间内从kube apis服务器往返。

如果您的扩展API服务器无法达到延迟要求,请考虑进行更改以满足该要求。您还可以在kube apiserver上设置enableagggregateddiscoverytimeout=false功能门来禁用超时限制。此不推荐使用的功能门将在将来的版本中删除。

What's next

5、Extend the Kubernetes API with CustomResourceDefinitions

 Kubernetes 的证书认证

今天让我们聊聊 Kubernetes 的公私钥和证书认证

本文内容会提及如何根据需要对 CA、公私钥进行组织并对集群进行设置。

Kubernetes 的组件中有很多不同的地方可以放置证书之类的东西。在进行集群安装的时候,我感觉有一百多亿个不同的命令参数是用来设置证书、密钥的,真不明白是怎么弄到一起工作的。

当然了,没有一百亿那么多的参数,不过的确很多的。比如 API Server 的参数吧,有大概 16 个参数是跟这些东西有关的(下面是节选):

--cert-dir string                           The directory where the TLS certs are located. If --tls-cert-file and --tls-private-key-file are provided, this flag will be ignored. (default "/var/run/kubernetes")
--client-ca-file string                     If set, any request presenting a client certificate signed by one of the authorities in the client-ca-file is authenticated with an identity corresponding to the CommonName of the client certificate.
--etcd-certfile string                      SSL certification file used to secure etcd communication.
--etcd-keyfile string                       SSL key file used to secure etcd communication.
--kubelet-certificate-authority string      Path to a cert file for the certificate authority.
--kubelet-client-certificate string         Path to a client cert file for TLS.
--kubelet-client-key string                 Path to a client key file for TLS.
--proxy-client-cert-file string             Client certificate used to prove the identity of the aggregator or kube-apiserver when it must call out during a request. This includes proxying requests to a user api-server and calling out to webhook admission plugins. It is expected that this cert includes a signature from the CA in the --requestheader-client-ca-file flag. That CA is published in the 'extension-apiserver-authentication' configmap in the kube-system namespace. Components recieving calls from kube-aggregator should use that CA to perform their half of the mutual TLS verification.
--proxy-client-key-file string              Private key for the client certificate used to prove the identity of the aggregator or kube-apiserver when it must call out during a request. This includes proxying requests to a user api-server and calling out to webhook admission plugins.
--requestheader-allowed-names stringSlice   List of client certificate common names to allow to provide usernames in headers specified by --requestheader-username-headers. If empty, any client certificate validated by the authorities in --requestheader-client-ca-file is allowed.
--requestheader-client-ca-file string       Root certificate bundle to use to verify client certificates on incoming requests before trusting usernames in headers specified by --requestheader-username-headers
--service-account-key-file stringArray      File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify ServiceAccount tokens. If unspecified, --tls-private-key-file is used. The specified file can contain multiple keys, and the flag can be specified multiple times with different files.
--ssh-keyfile string                        If non-empty, use secure SSH proxy to the nodes, using this user keyfile
--tls-ca-file string                        If set, this certificate authority will used for secure access from Admission Controllers. This must be a valid PEM-encoded CA bundle. Alternatively, the certificate authority can be appended to the certificate provided by --tls-cert-file.
--tls-cert-file string                      File containing the default x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). If HTTPS serving is enabled, and --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key are generated for the public address and saved to /var/run/kubernetes.
--tls-private-key-file string               File containing the default x509 private key matching --tls-cert-file.--tls-sni-cert-key namedCertKey             A pair of x509 certificate andprivate key file paths, optionally suffixed with a list of domain patterns which are fully qualified domain names, possibly with prefixed wildcard segments.Ifno domain patterns are provided, the names of the certificate are extracted.Non-wildcard matches trump over wildcard matches,explicit domain patterns trump over extracted names.For multiple key/certificate pairs,use the --tls-sni-cert-key multiple times.Examples:"example.crt,example.key"or"foo.crt,foo.key:*.foo.com,foo.com".(default[])

接下来是 Controller Manager 的:

--cluster-signing-cert-file string          Filename containing a PEM-encoded X509 CA certificate used to issue cluster-scoped certificates (default "/etc/kubernetes/ca/ca.pem")
--cluster-signing-key-file string           Filename containing a PEM-encoded RSA or ECDSA private key used to sign cluster-scoped certificates (default "/etc/kubernetes/ca/ca.key")
--root-ca-file string                       If set, this root certificate authority will be included in service account's token secret. This must be a valid PEM-encoded CA bundle.
--service-account-private-key-file string   Filename containing a PEM-encoded private RSA or ECDSA key used to sign service account tokens.

再来个 Kubelet:

--client-ca-file string                   If set, any request presenting a client certificate signed by one of the authorities in the client-ca-file is authenticated with an identity corresponding to the CommonName of the client certificate.
--tls-cert-file string                    File containing x509 Certificate used for serving HTTPS (with intermediate certs, if any, concatenated after server cert). If --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key are generated for the public address and saved to the directory passed to --cert-dir.
--tls-private-key-file string             File containing x509 private key matching --tls-cert-file.

本文假设读者:

  • 对 TLS 认证和 CA 有一些了解。
  • 能把这些东西跑起来,但是不知道为啥。

下面还会说明在 Kubernetes 中的不同 CA,以及不同 CA 的协同工作。

另外有些我在工作中学到的一些:

  • 不要用 CA 来检查 Service Account Key。Service Account key 有点古怪,他跟其他的 Key 不是一同处理的。
  • 如果 kubernetes 建立用户和组的方式不适合需求,可以(应该)设置一个认证代理。
  • API Server 如果设置了太多 CA,会显得有点乱。

这个题目有点复杂,如果阅读中发现任何问题请通知我。

PKI 和 Kubernetes

在阅读 Kubernetes 材料的过程中,我注意到一个词出现了很多次:“PKI”,我不很清楚这是个什么。

如果你有个在运行的 Kubernetes 集群,其中可能有几百上千个公钥私钥(客户端认证、服务认证等等)。

如果这几百个 Key 是独立的互不相关的,就会让安全性堕入泥潭。因此我们需要个 CA,CA 的职责就是签发证书,并告诉用户“这个公钥是我发的,靠谱”。

PKI 就是组织 Key 的方式 —— 什么 Key 是用什么 CA 签发的。

例如:

  • 可以为每个集群准备一个 CA,集群所有的私钥都从这个 CA 签发(Kubernetes 文档中多数是这个情况)。
  • 可以准备一个全局 CA,所有的私钥都从此而来。
  • 单独给服务使用一个 CA,对外可见;内部另外使用一个 CA 作为专门用途。
  • 还有其他。

我不是安全专家,所以不想说如何管理私钥和 CA 才更好。但是不管你用的什么样的模型,其实都可以跟 Kubernetes 协调工作。

下面根据需求来确认管理 PKI 的方式,以及如何在 Kubernetes 中实现。

Kubernetes 集群需要一个单根结构的 CA 么?不

如果你读了不少 Kubernetes 集群的安装文档,会注意到总有一步:设置一个 CA。Kelsey Hightower 的大作 “Kubernetes the hard way” 中是第二步,“在集群中信任 TLS ”中说:

每个 Kubernetes 集群都有一个集群根 CA。CA 一般用于集群中的组件验证 API Server 的合法性,在 API Serverl 来说,就是验证 kubelet 客户端的证书,诸如此类的。

基本上来说:

  1. 设置一个 CA
  2. 用这个 CA 生成不同的证书,给 Kubernetes 集群的不同组件使用。

如果不想为每个集群设置一个新的 CA 呢?可能有很多理由。但是我担心,最终还是需要提供一个根 CA。

这好像说上面的话是假的,其实可以使用很多不同的 CA 签发的证书来管理 Kubernetes。总的说来,还是要结合具体场景的需求。

接下来我们来探讨一下证书相关的参数,以及互相之间的关系。每一节都会包含一个可以定义的 CA。每一个都是独立的,并不需要一致。不过在实际操作中,可能你并不想管理 6 个不同的 CA。

API Server 的 TLS 证书(以及 CA)

–tls-cert-file string

包含缺省的 x509 https 认证的文件(可以包含 CA 证书),如果启用了 HTTPS 服务,又没有指定–tls-cert-file和–tls-private-key-file参数,就会在 /var/run/kubernetes生成一个自签名证书以及 Key

–tls-private-key-file

–tls-cert-file证书的 x509 私钥。

如果用 TLS 连接 API Server,就需要这两个参数来选择 API Server 使用的证书。

证书设置了之后,还需要给各个组件的 kubeconfig 文件进行相关设置。

current-context: my-context
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /path/to/my/ca.crt # 签发 API Server 证书的 CA 证书
    server: https://horse.org:4443
  name: my-cluster
kind: Config
users:
- name: green-user
  user:
    client-certificate: path/to/my/client/cert # 后面会讲
    client-key: path/to/my/client/key # 后面会讲

有个让我惊奇的事情就是——这个宇宙里面的几乎所有其他使用 TLS 的系统都会去 /etc/ssl 查找一个本机信任的 CA 列表,但是 Kubernetes 很傲娇,他不会去找,必须显式的进行告知签发 CA。

可以使用参数–kubeconfig /path/to/kubeconfig.yaml将配置文件分配给各个组件进行使用。

这样我们完成了第一个 CA 的设置:签发 API Server 证书的 CA。这个 CA 跟其他的 CA 可以不一致。

API Server 客户证书认证

–client-ca-file

如果设置了这一参数,所有的请求都应该使用该文件中所包含的 CA 签发的证书进行签署,证书中的 Common Name 会作为用户名进行使用。

Kubernetes 组件获得 API Server 认证的方法之一就是使用这一参数。

所有客户端证书都应该由这一 CA 签发(不需要和 API Server 的 CA 一致)。

当使用 kubeconfig 文件的时候,可以按照如下方式设置使用证书:

kind: Config
users:
- name: green-user
  user:
    client-certificate: path/to/my/client/cert
    client-key: path/to/my/client/key

Kubernetes 做了很多用户证书方面的假设(用户名就是 Common Name,Group 就是 Organization)。如果这些假设不符合需求,那么就应该停用客户端证书认证,改用认证代理。

请求 Header 的证书认证(或者:认证代理)

API server 参数

–requestheader-allowed-names stringSlice

–requestheader-username-headers 中指定的 Header 中包含用户名,这一参数的列表确定了允许有效的 Common Name,如果这一参数的列表为空,则所有通过–requestheader-client-ca-file校验的都允许通过。

–requestheader-client-ca-file string

针对收到的请求,在信任–requestheader-username-headers中指定的 Header 里面包含的用户名之前,首先会用这一 CA 对客户证书进行验证。

另外一个设置 Kubernetes 认证的方式就是认证代理。如果你对如何向 API Server 发送用户名和组有很多想法,可以设置一个代理,这一代理会使用 HTTP Header 将用户名和组发送给 API Server。

文档中简单的解释了一下工作方式。代理使用一个客户端证书表明身份,–requestheader-client-ca-file告知 API Server,该证书所属的 CA。

我觉得——API Server 有太多认证方式了(客户端认证、认证代理、Token 等等),让人很迷惑。建议用户尽量少的同时使用认证方式,便于管理、使用和除错。

service account 私钥(不是 CA 签发的)

API Server 参数

–service-account-key-file

PEM 编码的 X509 RSA 或者 ECDSA 的私钥或者公钥,用于检验 ServiceAccount 的 token。如果没指定的话,会使用–tls-private-key-file替代。文件中可以包含多个 Key,这一参数可以重复指定多个文件。

Controller Manager 参数

–service-account-private-key-file

PEM 编码的 X509 RSA 或者 ECDSA Key,用于签署 Service Account Token。

Controller Manager 使用私钥签署 Service Account Token。跟 Kubernetes 中使用的其他私钥不同的是,这个私钥是不支持同一 CA 验证的,因此上,需要给每个 Controller Manager 指定一致的私钥文件。

这个 Key 也不需要什么 CA 来做签署,生成很容易:

openssl genrsa -out private.key 4096

然后分发给每个 Controller Manager 和 API Server 就可以了。

使用和–tls-private-key-file一致的文件是可以工作的——只要你给每个 API Server 用的都是同一个 TLS Key(一般都这么做的吧?)。(这里我假设你运行的一个有高可用支持的,多个 API Server 和多个 Controller Manager同时运行的集群)

如果两个不同的 Controller Manager 用了两个不同的 Key,那就杯具了,他们会用各自的 Key 来生成 Token,最终导致无效判定。我觉得这点不太合理,Kubernetes 应该和其他方面一样,使用 CA 进行管理。通过对源码的月度,我觉得原因可能是 jwt-go 不支持 CA。

Kubelet 证书认证

总算到了 Kubelet 环节了,下面是 API Server 和 Kubelet 相关的内容:

API Server 参数

–kubelet-certificate-authority CA 证书的路径。

–kubelet-client-certificate TLS 证书文件

–kubelet-client-key TLS Key 文件

Kubelet 参数

–client-ca-file

请求中的客户端证书如果是由文件中的 CA 签署的,那么他的 Common Name 就会被用作 ID 进行认证。

–tls-cert-file

用来提供 HTTPS 服务的 x509 证书(其中也可包含中间人证书)。如果不提供–tls-cert-file和–tls-private-key-file,就会为主机地址生成一个自签名的证书和对应的 Key,并保存到–cert-dir目录里。

–tls-private-key-file

–tls-cert-file 对应的 Key

校验 kubelet 的请求是有用的,因为 Kubelet 的职责就是在主机上执行代码。

这里实际上有两个 CA,这里不准备深入描述,情况和 API Server 是一样的,Kubelet 用 TLS 来进行认证,也支持客户证书认证。

另外还要告知 API Server,用什么 CA 检查 Kubelet 的 TLS,另外用什么证书来跟 Kubelet 通信。

再说一次,这两个 CA 是可以不同的。

太多 CA 了

现在我们找到了五个不同的 CA,他们各自独立的为 Kubernetes 提供支持。

其实还有一些没讨论到的证书,不过希望本文能给你阅读官方文档提供一点帮助。

当然了,每个 CA 独立设置可能不是必要的,我是希望帮助读者理解这些东西如何设置使之符合各种需求,而不是简单的面向文档照本宣科。

 

kubernetes关键概念总结

  • service

每个service对应一个cluster IP,cluster IP对应的服务网段最初是在配置kube-apiserver、kube-controller-manager和kube-proxy的systemd unit时指定的,如kube-apiserver参数为--service-cluster-ip-range。

Service提供提供了一种稳定访问一组pod的方式。Service使用clusterIP:port(默认方式)对外暴露服务,将外部流量从clusterIP:port导入到service中定义的selector标签指定的endpoint的targetport端口上(默认情况下targetport将被设置为与port字段相同的值)。Kube-proxy则为service提供了一种实现负载均衡的策略。Endpoint会在service创建后被自动创建。

  • kube-dns

集群中可以通过配置Kube-dns来实现服务发现的功能。Kube-dns实现了服务名到cluster IP的映射关系。Kube-dns通常会为service赋予一个名为“service名称.namespace.svc.cluster.local”的A记录,用来解析service的cluster IP。如果访问default namespace下的服务,可以通过“service名称”直接访问;如果访问其他namespace下的服务,可以通过“service名称.namespace”访问。k8s会为每个容器提供默认的/etc/resolv.conf配置,内容为:

1
2
3
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.0.0.10
options ndots:5

集群通过查询/etc/resolv.conf文件的nameserver字段来确定dns服务器,该文件是在kubelet服务启动配置中指定—cluster-dns,并在服务启动后自动生成的。当用“service名称”访问服务时,最终会使用default.svc.cluster.local这条search记录拼接完整的服务名称;当使用“service名称.namespace”时,最终会使用svc.cluster.local这条search记录。

  • serviceaccount

Serviceaccount就是pod中的process访问kubernetes API的account。Serviceaccount只关联了一个secret资源作为token,该token也叫service-account-token,是真正在API server验证环节起作用的。

service-account-token分为3部分:

ca.crt:API Server的CA公钥证书,用于POD的process对API server服务端数字证书进行校验使用,由kube-controller-manager参数--root-ca-file指定;

namespace:secret所在的namespace值的base64编码

token:用API server私钥签发(sign)的bearer tokens的base64编码,用于POD访问API server的身份验证(Authorization header首部)

一旦API Server发现client发起的request使用的是service account token的方式,API Server就会自动采用signed bearer token方式进行身份校验。而request就会使用携带的service account token参与验证。该token是API Server在创建service account时用kube-controller-manager启动参数:--service-account-private-key-file指定的私钥签署(sign)的,同时必须指定kube-apiserver参数--service-account-key-file(如果没指定的话,会使用–tls-private-key-file替代)为该私钥对应的公钥,用来在认证阶段验证token(You must pass a service account private key file to the token controller in the controller-manager by using the --service-account-private-key-file option. The private key will be used to sign generated service account tokens. Similarly, you must pass the corresponding public key to the kube-apiserver using the --service-account-key-file option. The public key will be used to verify the tokens during authentication),也就是说该证书对通过CN和O指定了serviceaccount的授权权限。

通过authenticating后,API Server将根据Pod username所在的group system:serviceaccounts和system:serviceaccounts:(NAMESPACE)的权限对其进行authority 和admission control两个环节的处理。(Service Accounts have usernames with the system:serviceaccount: prefix and belong to groups with the system:serviceaccounts: prefix,形如system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT))

不管是自动生成的token还是手动创建的token的值都是一样的,因为进行签署token的–service-account-key-file是同一个。

Serviceaccount中的token是API server私钥签署的,POD在对API Server发起请求的时候会带上该token,以确保能够通过API server的认证。对serviceaccount的授权通过对serviceaccount对应的用户或组进行RBAC控制即可

 参见: https://k8smeetup.github.io/docs/admin/authorization/rbac/

  • tls-bootstrapping

当前该功能仅支持为kubelet生成证书。Bootstrap-token是在新建集群或者在现有集群中添加新节点时使用的,为kubelet提供tls客户端证书。Bootstrap-token被定义成一个特定类型的 secrets(bootstrap.kubernetes.io/token)。

 

  kubelet 发起的 CSR 请求都是由 controller manager 来做实际签署的,对于 controller manager 来说,TLS bootstrapping 下 kubelet 发起的 CSR 请求大致分为以下三种

    • nodeclient: kubelet 以 O=system:nodes 和 CN=system:node:(node name) 形式发起的 CSR 请求,仅在第一次启动时会产生;
    • selfnodeclient: kubelet client renew 自己的证书发起的 CSR 请求(与上一个证书就有相同的 O 和 CN),kubelet renew 自己作为 client 跟 apiserver 通讯时使用的证书产生;
    • selfnodeserver: kubelet server renew 自己的证书发起的 CSR 请求,kubelet 首次申请或后续 renew 自己的 10250 api 端口证书时产生

首次启动时,kube-apiserver会指定--token-auth-file=FILENAME来启用用户的token,同时该用户的token和apiserver的CA证书被写入了kubelet的bootstrap.kubeconfig文件中,这样在首次请求时,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 证书来与 apiserver 建立 TLS 通讯,使用 bootstrap.kubeconfig 中的用户kubelet-bootstrap(需要创建clusterRoBingding来将预设用户与内置的system:node-bootstrapper绑定到一起) 的Token 来向 apiserver 声明自己的 RBAC 授权身份(用户为kubelet-bootstrap,组为system:kubelet-bootstrap)。

export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')
cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"

绑定用户kubelet-bootstrap到内置ClusterRole(system:node-bootstrapper):kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --user=kubelet-bootstrap

对于bootstrap下的kubelet的CSR的审批可以手动审批,也可以自动审批:

手动审批:

需要将用户与内置的clusterrole system:node-strapper绑定,并注意设置证书过期时间(默认有效期为1年):设置kube-controller-manager参数--experimental-cluster-signing-duration设置为10年(防止证书过期):8760h0m0s

手动签发证书命令为:kubectl certificate approve XXX (xxx为CSR,使用kubectl get csr获取)

自动审批:

k8s针对bootstrap下kubelet发起的3种CSR给出了3种对应的clusterrole,想要kubelet能够自动续期,只要将适当的clusterrole绑定到kubelet自动续期时采用的用户或用户组上即可。基于3种clusterrole需要创建3个clusterrolebinding。1.8中已经创建了前两条clusterrole,还需要创建一条:

复制代码
# A ClusterRole which instructs the CSR approver to approve a node requesting a
# serving cert matching its client cert.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups: ["certificates.k8s.io"]
  resources: ["certificatesigningrequests/selfnodeserver"]
  verbs: ["create"]
复制代码

 

3个clusterrole对应的clusterbingding如下:

复制代码
# 自动批准 system:bootstrappers 组用户 TLS bootstrapping 首次申请证书的 CSR 请求
kubectl create clusterrolebinding node-client-auto-approve-csr --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient --group=system:bootstrappers

# 自动批准 system:nodes 组用户更新 kubelet 自身与 apiserver 通讯证书的 CSR 请求
kubectl create clusterrolebinding node-client-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient --group=system:nodes

# 自动批准 system:nodes 组用户更新 kubelet 10250 api 端口证书的 CSR 请求
kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeserver --group=system:nodes
复制代码

启动自动续期:kubelet启动时增加--feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true,--rotate-certificates;kube-controller-manager启动时增加--feature-gates=RotateKubeletServerCertificate=true

  • kubelet端口

10250 kubelet API –kublet暴露出来的端口,通过该端口可以访问获取node资源以及状态
10255 readonly API –kubelet暴露出来的只读端口,访问该端口不需要认证和鉴权,该http server提供查询资源以及状态的能力

  • 参考:

    https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/

    https://kubernetes.io/docs/tasks/tls/certificate-rotation/

 

kubernete的证书总结

服务端保留公钥和私钥,客户端使用root CA认证服务端的公钥。

kubernetes的证书类型主要分为3类:

  • serving CA: 用于签署serving证书,该证书用于加密https通信。用于签署kubernetes API serving证书的CA也可以用于签署API server插件的serving证书,可能会用到不同的CA
  • client CA: 用于签署客户端证书,同时也被API server插件用来对客户端发来的证书进行认证。用于签署kubernetes API serving证书的client CA也可以用于签署API server插件的serving证书,可能会用到不同的CA
  • RequestHeader client CA: 该CA用于签署API server代理客户端证书,拥有代理证书的客户端可以有效地伪装成任何身份。当运行在aggregator之后时,该CA必须与前述aggregator代理客户端证书的CA一致()

serving 证书:
--tls-cert-file和--tls-private-key-file,API server用这两个选项来认证连接到自己的TLS。这两个证书也是CA(可以是自签CA)签署的。由于客户端节点可能会拒绝自签CA,因此需要将该CA分发给客户端节点,并在客户端指定该CA。如下kubelet的kubeconfig中的certificate-authority就指定了用于认证tls证书的CA。--tls-cert-file中需要有server字段的名称。API server和kubelet(当需要认证到kubelet的请求时)都有这两个选项,工作原理一样。

current-context: my-context
apiVersion: v1
clusters:
- cluster:
certificate-authority: /path/to/my/ca.crt # CERTIFICATE AUTHORITY THAT ISSUED YOUR TLS CERT
server: https://horse.org:4443 # this name needs to be on the certificate in --tls-cert-file
name: my-cluster
kind: Config
users:
- name: green-user
user:
client-certificate: path/to/my/client/cert
client-key: path/to/my/client/key

client 证书:
--client-ca-file:任何带有 client-ca-file 签名的客户端证书的请求,都将通过客户端证书中 Common Name 对应的标识进行身份认证,证书中的 Common Name 会作为用户名,Organization作为组来使用。默认情况下,API Server使用该选项会自动创建一个名为extension-apiserver-authentication,位于kube-system命名空间的ConfigMap ,该ConfigMap 中包含了--client-ca-file指定的CA。
API server的--kubelet-certificate-authority、--kubelet-client-certificate、--kubelet-client-key 和kubelet的--client-ca-file为一组选项,用于对kubelet进行认证(kubelet 组件在工作时,采用主动的查询机制,即定期请求 apiserver 获取自己所应当处理的任务)

RequestHeader client CA:
主要涉及3个选项--requestheader-client-ca-file、--proxy-client-cert-file、--proxy-client-key-file。代理(如aggregator)使用--proxy-client-cert-file、--proxy-client-key-file来请求API Server,API Server使用--requestheader-client-ca-file指定的证书来认证代理的证书。这三个选项都设置在API server的flag中,即aggregator一方面作为API server认证来自client的证书,一方面作为client,使用自身的代理证书向API server请求认证。
当kubernetes对应的客户端证书中的usernames和group与自己需求不符合时(无法认证或权限不足等),可以使用认证代理(代理使用另一套证书请求API server)

可以看到serving证书是通过TLS来进行认证,client证书通过用户名(Common Name)和组(Organization)进行认证;RequestHeader client证书认证方式与client证书认证方式类似

证书的验证:

显示插件API server支持的证书:openssl s_client -connect <service-cluster-ip>:443更多

验证证书是否由CA签署:openssl verify -CAfile ca.crt   the-certificate.crt

更多参见Certificate Issues

 

serviceaccount:参见http://www.cnblogs.com/charlieroro/p/8484711.html中serviceaccount一节

参考

https://jvns.ca/blog/2017/08/05/how-kubernetes-certificates-work/
https://kubernetes.io/docs/concepts/cluster-administration/certificates

 
 

etcd 启用 https

文章目录
  • 1, 生成 TLS 秘钥对
  • 2,拷贝密钥对到所有节点
  • 3,配置 etcd 使用证书
  • 4,测试 etcd 是否正常
  • 5,配置 kube-apiserver 使用 CA 连接 etcd
  • 6,测试 kube-apiserver
  • 7,未解决的问题

Kubernetes:10---服务配置选项(kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy)

https://dongshao.blog.csdn.net/article/details/111771687

 

 

 

 

 

posted @ 2021-03-04 15:19  highly  阅读(183)  评论(0编辑  收藏  举报