AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
# 创建 TLS 证书和秘钥 Kubernetes 系统的各个组件使用TLS双向认证加密通讯,双向认证就是客户端对服务端进行证书验证时,服务端也对客户端进行证书验证,服务端和客户端都需要配置证书,但客户端的证书中不需要包含域名或ip地址。 **证书**:根据认证对象可以将证书分成三类:服务器证书server cert,客户端证书client cert,对等证书peer cert(表示既是server cert又是client cert),在kubernetes 集群中需要的证书种类如下: **etcd** 节点需要标识自己服务的server cert,也需要client cert与etcd集群其他节点双向认证,使用同一个证书即可peer cert。 **master** 节点需要标识 apiserver服务的server cert,也需要client cert连接etcd集群双向认证,使用同一个证书即可peer cert。 **kubectl,kube-proxy** 作为客户端与api通信需要client cert,因此证书请求中 hosts 字段可以为空。 **kubelet** 证书不是手动生成的,kubelet启动时会向apiserver发送证书签名请求(TLS BootStrap功能),签名请求由controller-manager处理,返回给kubelet一个client cert 和一个server cert,client cert作为客户端证书与api实现TLS双向认证,server cert是kubelet作为服务端对外提供服务时使所使用的,kubelet对外提供服务是否使用TLS是在api的配置文件里配置的。 **controller-manager 和 scheduler 与 apiserver** 部署在同一台机器,一般使用http方式访问apiserver,不需要server证书也不需要client证书。 **安装 CFSSL工具** ~~~ mkdir -p /usr/local/bin && cd /usr/local/bin wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O cfssljson wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O cfssl wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O cfssl-certinfo chmod +x * echo "export PATH=/usr/local/bin:$PATH" >> /etc/profile ~~~ 这玩意就是一个创建CA和颁发证书的软件,可以看做是一个简化版的openssl, 相比openssl,这个用起来很简单。可以在任何一台机器上安装并进行本章节的所有操作,也可以在K8S集群以外的机器上操作,将生成的证书拷贝到K8S集群机器上即可。 **创建 ca-config文件** ~~~ mkdir /root/ssl && cd /root/ssl cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF ~~~ ca-config.json:配置文件,简单理解就是通过CA签名时的规则,签出来的证书自带以下属性: expiry:证书过期时间,876000小时; signing:表示证书可用于签名其他证书;生成的 ca.pem 证书中 CA=TRUE; server auth:表示 client 可以使用该 CA 对 server 提供的证书进行验证; client auth:表示 server 可以使用该 CA 对 client 提供的证书进行验证; **创建 CA 证书签名请求** ~~~ cat > ca-csr.json <<EOF { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF ~~~ "CN":值是一些 ca 用来确定哪些域生成证书,如果提供 "www" 域名,这些 CA 将经常为 "www(例如 www.example.net)" 和 "bare"(例如 example.net)域名提供证书。kube-apiserver 从证书中提取该字段作为请求的用户名(User name );浏览器使用该字段验证网站是否合法; "key":示例中的值是大多数 CA 支持的默认值。(在这种情况下甚至可以省略;这里显示是为了完整性) "C": country。国家。 "L": locality or municipality (such as city or town name)。地点或城市(例如城市或城镇名字) "O": organisation。组织、机构、团体、安排。kube-apiserver 从证书中提取该字段作为请求用户所属的组(Group) "OU": organisational unit, such as the department responsible for owning the key; it can also be used for a "Doing Business As" (DBS) name。组织单位,例如部门负责所属的 key;它也可以用于 “Doing Business As”(DBS)名称。 "ST": the state or province。州或省 **生成 CA 证书和私钥** ~~~ cfssl gencert -initca ca-csr.json |cfssljson -bare ca ls ca* ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem ~~~ ca.csr:签名请求(这玩意是根据下面的ca-csr.json的描述生成的,根证书就是通过这玩意给其他证书签名的,但现在还没有根证书,我们是要申请根证书,所以这玩意是被CFSSL这个软件给处理了,然后得到了一个完成自签名的根证书和私钥,之后就可以用根证书私钥给其他证书签名了) ca-csr.json:一堆描述 ca-key.pem:根证书私钥(用于给其他证书公钥签名和解密根公钥) ca.pem:根证书公钥(已经通过自签名,放在客户端作为权威颁发机构验证其他证书) **根证书已经创建好了,接下来用根证书签名其他服务用到的证书。** **创建api-server证书签名请求** ~~~ vim kubernetes-csr.json { "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.50.103", "192.168.50.101", "192.168.50.102", "10.254.0.1", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } ~~~ hosts:如果你去网上花钱购买权威机构颁发的公网证书,这个字段只能填写域名不能填写ip,但咱们是自己搭建的CA并且是用于内网通信,所以这里直接填写ip。该证书是给apiserver服务用的,要填写所有api服务的ip,给api做负载均衡的ip,和 kubernetes的内部服务IP(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如10.254.0.1)。 192.168.50.101和192.168.50.102是我的api服务器ip,192.168.50.103是api负载均衡地址,其他都是固定的不要改动。 **注意**:如果计划在阿里云等云环境上搭建,提前创建slb负载均衡,将slb的ip写到证书中,slb的ip是随机的,后创建slb没办法指定证书中的ip。 **生成 api-server 证书** ~~~ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes ls kubernetes* kubernetes.csr kubernetes-csr.json kubernetes-key.pem kubernetes.pem ~~~ 再解释一波,之后就不再解释了,生成的其他证书原理全都是一样的。 kubernetes.csr:证书签名请求,通过下面的kubernetes-csr.json描述生成的,有了签名请求才能申请被签名) kubernetes-csr.json :证书描述 kubernetes-key.pem :证书私钥 kubernetes.pem:被根证书ca-key.pem签过名的证书公钥 **创建etcd证书签名请求** ~~~ vim etcd-csr.json { "key": { "algo": "rsa", "size": 2048 }, "names": [ { "O": "etcd", "OU": "etcd Security", "L": "Beijing", "ST": "Beijing", "C": "CN" } ], "CN": "etcd", "hosts": [ "127.0.0.1", "localhost", "192.168.50.101", "192.168.50.102", "192.168.50.1" ] } ~~~ **生成etcd证书** ~~~ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd ls etcd* etcd.csr etcd-csr.json etcd-key.pem etcd.pem ~~~ **创建kube-proxy证书签名请求** ~~~ cat > kube-proxy-csr.json <<EOF { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF ~~~ CN: 指定该证书的 User 为 system:kube-proxy;kube-apiserver 预定义的 RoleBinding cluster-admin 将 User system:kube-proxy 与 Role system:node-proxy 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限; hosts:为3台etcd的ip地址 **生成 kube-proxy证书* ~~~ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy ls kube-proxy* kube-proxy.csr kube-proxy-csr.json kube-proxy-key.pem kube-proxy.pem ~~~ **创建calico证书签名请求** ~~~ cat > calico-csr.json <<EOF { "CN": "calico", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF ~~~ **生成calico证书** ~~~ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes calico-csr.json | cfssljson -bare calico ls calico* calico.csr calico-csr.json calico-key.pem calico.pem ~~~ calico是网络组件,它只需要访问etcd服务,证书为客户端证书,所以hosts可以为空。 **创建 admin 证书签名请求** ~~~ cat > admin-csr.json <<EOF { "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:masters", "OU": "System" } ] } EOF ~~~ **生成 admin 证书** ~~~ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin ls admin* admin.csr admin-csr.json admin-key.pem admin.pem ~~~ 这个证书是给kubectl客户端工具连接api-server用的 **官方解释**:apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权,apiserver 预定义了一些RoleBindings,如 cluster-admin 将 Group system:master 与 Role cluster-admin 绑定,该 Role 授予了调用 apiserver 的所有权限。 OU 指定该证书的 Group 为 system:master,kubelet 使用该证书访问apiserver 时,由于证书被CA签名,所以认证通过,同时由于证书组为经过预授权的 system:master,所以被授权予访问所有API的权限。 **个人解释**:搞懂这个赋权的过程得先了解RBAC,RBAC简单点说就是创建一个账号serviceaccount,再创建一组访问api的权限规则role如能读取pod读取deploy,在创建一个rolebindings将账号和权限绑在一起,以后使用这个账号就有访问api的相应权限了,系统里预定义了一些rolebindings,比如这个cluster-admin,这玩意将Group system:master 与 Role cluster-admin 绑定,该 Role 授予了调用 apiserver 的所有权限,而证书中的OU 指定该证书的 Group 为 system:master,所以这个证书就有了访问api的所有权限,很绕么?那就对了,读十遍后就理解了。等安装完k8s后可以用kubectl get clusterrolebinding cluster-admin -o yaml看到这个绑定。 **整理文件** ~~~ mkdir -p /etc/kubernetes/ssl cp *.pem /etc/kubernetes/ssl ~~~ ---------------------------分割线----------------------------- 至此K8S集群中所有组件需要的证书生成完毕,不包括K8S外的其他扩展组件calico,harbor等,在安装扩展组件章节会单独介绍。 **这就完了?当然没有** kubectl,kubelet,kube-proxy和apiserver的通信并不是直接使用证书,而是将证书打包在各自的kubeconfig文件中,程序读取这个文件得到证书和一些其他配置信息,所以有了证书后还需要给服务创建对应的kubeconfig文件。