Kubernetes权威指南:从Docker到Kubernetes实践全接触(第4版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.4 Kubernetes集群的安全设置

2.4.1 基于CA签名的双向数字证书认证方式

在一个安全的内网环境中,Kubernetes的各个组件与Master之间可以通过kube-apiserver的非安全端口http://<kube-apiserver-ip>:8080进行访问。但如果API Server需要对外提供服务,或者集群中的某些容器也需要访问API Server以获取集群中的某些信息,则更安全的做法是启用HTTPS安全机制。Kubernetes提供了基于CA签名的双向数字证书认证方式和简单的基于HTTP Base或Token的认证方式,其中CA证书方式的安全性最高。本节先介绍如何以CA证书的方式配置Kubernetes集群,要求Master上的kube-apiserver、kube-controller-manager、kube-scheduler进程及各Node上的kubelet、kube-proxy进程进行CA签名双向数字证书安全设置。

基于CA签名的双向数字证书的生成过程如下。

(1)为kube-apiserver生成一个数字证书,并用CA证书签名。

(2)为kube-apiserver进程配置证书相关的启动参数,包括CA证书(用于验证客户端证书的签名真伪)、自己的经过CA签名后的证书及私钥。

(3)为每个访问Kubernetes API Server的客户端(如kube-controller-manager 、kube-scheduler、kubelet、kube-proxy及调用API Server的客户端程序kubectl等)进程都生成自己的数字证书,也都用CA证书签名,在相关程序的启动参数里增加CA证书、自己的证书等相关参数。

1.设置kube-apiserver的CA证书相关的文件和启动参数

使用OpenSSL工具在Master服务器上创建CA证书和私钥相关的文件:

          # openssl genrsa -out ca.key 2048
          # openssl req -x509-new -nodes -key ca.key -subj "/CN=k8s-master" -days 5000
      -out ca.crt
          # openssl genrsa -out server.key 2048

注意:在生成ca.crt时,-subj参数中“/CN”的值为Master主机名。

准备master_ssl.cnf文件,该文件用于x509 v3版本的证书。在该文件中主要需要设置Master服务器的hostname(k8s-master)、IP地址(192.168.18.3),以及Kubernetes Master Service的虚拟服务名称(kubernetes.default等)和该虚拟服务的ClusterIP地址(169.169.0.1)。

master_ssl.cnf文件的示例如下:

          [req]
          req_extensions = v3_req
          distinguished_name = req_distinguished_name
          [req_distinguished_name]
          [ v3_req ]
          basicConstraints = CA:FALSE
          keyUsage = nonRepudiation, digitalSignature, keyEncipherment
          subjectAltName = @alt_names
          [alt_names]
          DNS.1 = kubernetes
        DNS.2 = kubernetes.default
        DNS.3 = kubernetes.default.svc
        DNS.4 = kubernetes.default.svc.cluster.local
        DNS.5 = k8s-master
        IP.1 = 169.169.0.1
        IP.2 = 192.168.18.3

基于master_ssl.cnf创建server.csr和server.crt文件。在生成server.csr时,-subj参数中“/CN”的值需为Master的主机名:

        # openssl req -new -key server.key -subj "/CN=k8s-master" -config master_ssl.cnf
    -out server.csr
        # openssl x509-req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days
    5000-extensions v3_req -extfile master_ssl.cnf-out server.crt

在全部执行完后会生成6个文件:ca.crt、ca.key、ca.srl、server.crt、server.csr、server.key。

将这些文件复制到一个目录下(例如/var/run/kubernetes/),然后设置kube-apiserver的三个启动参数“--client-ca-file”“--tls-cert-file”和“--tls-private-key-file”,分别代表CA根证书文件、服务端证书文件和服务端私钥文件:

        --client-ca-file=/var/run/kubernetes/ca.crt
        --tls-private-key-file=/var/run/kubernetes/server.key
        --tls-cert-file=/var/run/kubernetes/server.crt

同时,可以关闭非安全端口(设置--insecure-port=0),设置安全端口为6443(默认值):

        --insecure-port=0
        --secure-port=6443

最后重启kube-apiserver服务。

2.设置kube-controller-manager的客户端证书、私钥和启动参数

代码如下:

        $ openssl genrsa -out cs_client.key2048
        $ openssl req -new -key cs_client.key -subj "/CN=k8s-master"-out cs_client.csr
        $ openssl x509-req -in cs_client.csr -CA ca.crt -CAkey ca.key-CAcreateserial
    -out cs_client.crt-days 5000

其中,在生成cs_client.crt时,-CA参数和-CAkey参数使用的是API Server的ca.crt和ca.key文件。然后将这些文件复制到一个目录下(例如/var/run/kubernetes/)。

接下来创建/etc/kubernetes/kubeconfig文件(kube-controller-manager与kube-scheduler共用),配置客户端证书等相关参数,内容如下:

        apiVersion: v1
        kind: Config
        users:
        - name: controllermanager
          user:
            client-certificate: /var/run/kubernetes/cs_client.crt
            client-key: /var/run/kubernetes/cs_client.key
        clusters:
        - name: local
          cluster:
            certificate-authority: /var/run/kubernetes/ca.crt
            server: https://192.168.18.3:6443
        contexts:
        - context:
            cluster: local
            user: controllermanager
          name: my-context
        current-context: my-context

然后设置kube-controller-manager服务的启动参数:

        --service-account-key-file=/var/run/kubernetes/server.key
        --root-ca-file=/var/run/kubernetes/ca.crt
        --kubeconfig=/etc/kubernetes/kubeconfig

最后重启kube-controller-manager服务。

3.设置kube-scheduler启动参数

kube-scheduler复用上一步kube-controller-manager创建的客户端证书,配置启动参数:

        --kubeconfig=/etc/kubernetes/kubeconfig

重启kube-scheduler服务。

4.设置每个Node上kubelet的客户端证书、私钥和启动参数

首先,复制kube-apiserver的ca.crt和ca.key文件到Node上,在生成kubelet_client.crt时-CA参数和-CAkey参数使用的是API Server的ca.crt和ca.key文件;在生成kubelet_client.csr时,将-subj参数中的“/CN”设置为本Node的IP地址:

        $ openssl genrsa -out kubelet_client.key2048
        $ openssl req -new -key kubelet_client.key -subj "/CN=192.168.18.4"-out
    kubelet_client.csr
        $ openssl x509-req -in kubelet_client.csr -CA ca.crt -CAkey ca.key
    -CAcreateserial -out kubelet_client.crt-days 5000

将这些文件复制到一个目录下(例如/var/run/kubernetes/)。

接下来创建/etc/kubernetes/kubeconfig文件(kubelet和kube-proxy进程共用),配置客户端证书等相关参数,内容如下:

        apiVersion: v1
        kind: Config
        users:
        - name: kubelet
          user:
            client-certificate: /etc/kubernetes/ssl_keys/kubelet_client.crt
            client-key: /etc/kubernetes/ssl_keys/kubelet_client.key
        clusters:
        - name: local
          cluster:
            certificate-authority: /etc/kubernetes/ssl_keys/ca.crt
            server: https://192.168.18.3:6443
        contexts:
        - context:
            cluster: local
            user: kubelet
          name: my-context
        current-context: my-context

然后设置kubelet服务的启动参数:

        --kubeconfig=/etc/kubelet/kubeconfig

最后重启kubelet服务。

5.设置kube-proxy的启动参数

kube-proxy复用上一步kubelet创建的客户端证书,配置启动参数:

        --kubeconfig=/etc/kubernetes/kubeconfig

重启kube-proxy服务。

至此,一个基于CA的双向数字证书认证的Kubernetes集群环境就搭建完成了。

6.设置kubectl客户端使用安全方式访问API Server

在使用kubectl对Kubernetes集群进行操作时,默认使用非安全端口8080对API Server进行访问,也可以设置为安全访问API Server的模式,需要设置3个证书相关的参数“——certificate -authority”“--client-certificate”和“--client-key”,分别表示用于CA授权的证书、客户端证书和客户端密钥。

◎ --certificate-authority:使用为kube-apiserver生成的ca.crt文件。

◎ --client-certificate:使用为kube-controller-manager生成的cs_client.crt文件。

◎ --client-key:使用为kube-controller-manager生成的cs_client.key文件。

同时,指定API Server的URL地址为HTTPS安全地址(例如https://k8s-master:443),最后输入需要执行的子命令,即可对API Server进行安全访问了:

          # kubectl --server=https://192.168.18.3:6443
      --certificate-authority=/etc/kubernetes/ssl_keys/ca.crt
      --client-certificate=/etc/kubernetes/ssl_keys/cs_client.crt
      --client-key=/etc/kubernetes/ssl_keys/cs_client.key get nodes
          NAME            STATUS    AGE
          k8s-node-1     Ready     1h

2.4.2 基于HTTP Base或Token的简单认证方式

除了提供了基于CA的双向数字证书认证方式,Kubernetes也提供了基于HTTP Base或Token的简单认证方式。各组件与API Server之间的通信方式仍然采用HTTPS,但不使用CA数字证书。

采用基于HTTP Base或Token的简单认证方式时,API Server对外暴露HTTPS端口,客户端提供用户名、密码或Token来完成认证过程。需要说明的是,kubectl命令行工具比较特殊,它同时支持CA双向认证和简单认证两种模式与API Server通信,其他客户端组件只能配置为双向安全认证或非安全模式与API Server通信。

1.基于HTTP Base认证的配置过程

(1)创建包括用户名、密码和UID的文件basic_auth_file,放置在合适的目录下,例如/etc/kuberntes目录。需要注意的是,这是一个纯文本文件,用户名、密码都是明文。

        # vi /etc/kubernetes/basic_auth_file
        admin,admin,1
        system,system,2

(2)设置kube-apiserver的启动参数“--basic-auth-file”,使用上述文件提供安全认证:

        --secure-port=6443
        --basic-auth-file=/etc/kubernetes/basic_auth_file

然后,重启API Server服务。

(3)使用kubectl通过指定的用户名和密码来访问API Server:

        # kubectl --server=https://192.168.18.3:6443--username=admin --password=admin
    --insecure-skip-tls-verify=trueget nodes
        NAME            STATUS    AGE
        k8s-node-1     Ready     1h

2.基于Token认证的配置过程

(1)创建包括用户名、密码和UID的文件token_auth_file,放置在合适的目录下,例如/etc/kuberntes目录。需要注意的是,这是一个纯文本文件,用户名、密码都是明文。

        $ cat /etc/kubernetes/token_auth_file
        admin,admin,1
        system,system,2

(2)设置kube-apiserver的启动参数“--token-auth-file”,使用上述文件提供安全认证:

        --secure-port=6443
        --token-auth-file=/etc/kubernetes/token_auth_file

然后,重启API Server服务。

(3)用curl验证和访问API Server:

        $ curl -k --header "Authorization:Bearer admin"
    https://192.168.18.3:6443/version
        {
          "major": "1",
          "minor": "14",
          "gitVersion": "v1.14.0",
          "gitCommit": "641856db18352033a0d96dbc99153fa3b27298e5",
          "gitTreeState": "clean",
          "buildDate": "2019-03-25T15:45:25Z",
          "goVersion": "go1.12.1",
          "compiler": "gc",
          "platform": "linux/amd64"
        }