# 创建 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文件。
- 部署介绍
- 一,系统初始化操作
- 二,创建TLS证书
- 三,创建kubeconfig文件
- 四,安装etcd集群
- 五,部署master节点
- 六,部署node节点
- 附,新增node节点
- 七,网络插件calico
- 八,安装DNS组件
- 九,安装dashboard
- 十,服务发布nginx-ingress
- 十一,prometheus监控部署
- 十二,prometheus自定义监控和报警
- 十三,Harbor私有仓库
- 十四,NFS数据持久化
- 其他
- linux相关文档
- centos7.4搭建openvpn
- docker-compose搭建ldap
- docker-compose搭建openvpn
- docker-compose搭建superset
- docker-compose搭建jenkins
