K8S-二进制文件部署安全高可用集群
前言:
在正式环境中,为确保Master的高可用,并启用安全访问机制,至少包括以下几个方面:
1. Master的kube-apiserver,kube-controller-mansger,kube-scheduler服务至少以三节点的多实例方式部署。
2. Master 启用基于CA认证的HTTPS安全机制。
3. etcd至少以3个节点的集群模式部署。
4. etcd集群启用基于CA认证的HTTPS安全机制。
5. Master 启用RBAC授权模式。
在master的3个节点之前,应通过一个负载均衡器对客户端的唯一访问入口地址,负载均衡可以选择的方案较多,本文以Haproxy搭配keepalived为例。
环境准备:
master:192.168.18.3-5
VIP: 192.168.18.100
下面分别对etcd,负载均衡器,Master,node等组件如何进行高可用部署,关键配置,CA认证配置进行详细说明。
一、创建CA根证书。
自制CA机构,etcd和k8s在制作CA证书时,均需要基于CA根证书,本文以为k8s和etcd使用同一套CA根证书为例,对CA根证书的制作进行说明。
创建CA根证书,私钥ca.key、证书文件ca.crt.
openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=192.168.18.3" -days 36500 -out ca.crt
将生成的ca.key和ca.crt保存在/etc/kubernetes/pki目录下。
二、部署安全的ETCD高可用集群
etcd作为集群的主数据库,在安装kubernetes各服务组件之前需要首先安装启动。
在GitHub官网下载etcd二进制文件,解压缩得到etcd和etcdctl文件,将他们复制到/usr/bin目录下。
2.1 创建etcd自启动脚本
[Unit] Description=etcd key-value store Documentation=https://github.com/etcd-io/etcd After=network.target [Service] EnvironmentFile=/etc/etcd/etcd.conf
ExecStart=/usr/bin/etcd
Restart=always [Install] WantedBy=multi-user.target
其中,EnvironmentFile需要指定配置文件的全路径。
2.2 创建ETCD的CA证书
创建x509 v3配置文件etcd_ssl.cnf,其中subjectAltName参数(alt_names)包括所有的etcd主机的IP地址。
[ req ] req_extensions = v3_req distinguished_name = req_distinguished_name [ req_distinguished_name ] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation,digitaSignature, keyEncipherment subjectAltName = @alt_names [ alt_names ] IP.1 = 192.168.18.3 IP.2 = 192.168.18.4 IP.3 = 192.168.18.5
使用openssl创建etcd的服务端CA证书,包括etcd_server.key和etcd_server.crt文件。将其保存在/etc/etcd/pki目录下。
openssl genrsa -out etcd_server.key 2048 openssl req -x509 -new -nodes -key etcd_server.key -config etcd_ssl.cnf -subj "/CN=etcd-server" -out etcd_server.csr
openssl -x509 -req -in etcd_server.csr -CA /etc/kubernetes/pki/ca.crt -CAkey=/etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_server.crt
因为是双向HTTPS认证,还需要创建客户端使用的CA证书,包括etcd_clint.key和etcd_clint.crt,将其保存到/etc/etcd/pki目录下,后续供apiserver连接使用。
openssl genrsa -out etcd_clint.key 2048 openssl req -x509 -new -nodes -key etcd_clint.key -config etcd_ssl.cnf -subj "/CN=etcd-server" -out etcd_client.csr openssl -x509 -req -in etcd_clint.csr -CA /etc/kubernetes/pki/ca.crt -CAkey=/etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out etcd_clint.crt
2.3 etcd参数配置说明
# 节点1配置 ETCD_NAME=etcd1 # 节点名称,唯一 ETCD_DATE_DIR =/rtc/etcd/data # etcd数据存储目录 ETCD_CERT_FILE=/etc/etcd/pki/etcd_server.crt ETCD_KEY_FILE=/etc/etcd/pki/etcd_server.key ETCD_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt ETCD_CLIENT_CERT_AUTH=/etc/true # 开启客户端证书认证 ETCD_LISTEN_CLIENT_URLS=https://192.168.18.3:2379 # 为客户端提供的监听地址 ETCD_ADVERTISE_CLIENT_URLS=https://192.168.18.3:2379 # 其他节点监听的地址 ETCD_PEER_CERT_FILE=/etc/etcd/pki/etcd_server.crt # 集群内各节点相互认证的证书 ETCD_PEER_KEY_FILE=/etc/etcd/pki/etcd_server.key # key ETCD_PEER_TRUSTED_CA_FILE=/etc/kubernetes/pki/ca.crt # 根证书 ETCD_LISTEN_PEER_URLS=https://192.168.18.3:2380 ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.18.3:2380 ETCD_INITIAL_CLUSTER_TOKEN=etcd-cluster # 集群名称 ETCD_INITIAL_CLUSTER="etcd1=https://192.168.18.3:2380,etcd2=https://192.168.18.4:2380,etcd1=https://192.168.18.5:2380" # 集群各节点的endpoint
ETCD_INITIAL_CLUSTER_STATE=new # 新建集群为new,存在为existing
节点二配置
.....
主要配置参数包括为客户端和集群及其他节点配置的各监听URL地址(均为HTTPS),并配置相应的CA证书。
三、部署安全的kubernetes Master高可用集群
在Master节点需要部署的服务包含etcd,apiserver,controller-manager和scheduler。
在node节点需要部署dockers,kubelet,和kube-proxy。
将kubernetes二进制可执行文件拷贝到/usr/bin目录下,然后创建启动脚本service。
3.1 部署apiserver
设置apiserver需要的CA相关证书,准备master_ssl.cnf文件用于生成x509 v3版本的证书。
[ req ] req_extensions = v3_req distinguished_name = req_distinguished_name [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation,digitaSignature, 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-1 DNS.6 = k8s-2 DNS.7 = k8s-3 IP.1 = 169.169.0.1 # master service 虚拟服务的clusterip地址 IP.2 = 192.168.18.3 IP.3 = 192.168.18.4 IP.4 = 192.168.18.5 IP.5 = 192.168.18.100 # 负载均衡地址
3.2 创建apiserver服务端的CA证书,将其保存到/etc/kubernetes/pki目录下:
openssl genrsa -out apiserver.key 2048 openssl req -x509 -new -nodes -key apiserver.key -config master_ssl.cnf -subj "/CN=192.168.18.3" -out apiserver.csr openssl -x509 -req -in apiserver.csr -CA /etc/kubernetes/pki/ca.crt -CAkey=/etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -extensions v3_req -extfile etcd_ssl.cnf -out apiserver.crt
3.3 创建apiserver客户端的CA证书,将其保存到/etc/kubernetes/pki目录下。
openssl genrsa -out apiserver_clint.key 2048 openssl req -x509 -new -nodes -key apiserver_clint.key -subj "/CN=admin" -out apiserver_client.csr openssl -x509 -req -in apiserver_clint.csr -CA /etc/kubernetes/pki/ca.crt -CAkey=/etc/kubernetes/pki/ca.key -CAcreateserial -days 36500 -out apiserver_clint.crt
3.4 创建apiserver启动脚本service
[Unit] Description=kuberbetes API Server Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] EnvironmentFile=/etc/kubernetes/apiserver ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS Restart=always [Install] WantedBy=multi-user.target
3.5 /etc/kubernetes/apiserver 内容参数详解
KUBE_API_ARGS="--INSECURE-PORT=0 \ # 0表示关闭http访问 --secure-port=6443 \ # https端口 --tls_cert-file=/etc/kubernetes/pki/apiserver.crt \ # 服务端证书 --tls-private-key-file=/etc/kubernetes/pki/apiserver.key \ # 服务端私钥 --client-ca-file=/etc/kubernetes/pki/ca.crt \ # CA --apiserver-count=3 --endpoint-reconciler-type=master-count \ # 实例数量 --etcd-server=https://192.168.18.3:2379,https://192.168.18.4:2379,https://192.168.18.5:2379 \ # 连接etcd的url列表 --etcd-cafile=/etc/kubernetes/pki/ca.crt \ # etcd使用的根证书路径 --etcd-certfile=/etc/kubernetes/pki/etcd_client.crt \ # etcd客户端CA证书文件,告诉APIServer拿着这个客户端证书去连接etcd --etcd-keyfile=/etc/kubernetes/pki/etcd_client.key \ # etcd客户端私钥 --service-cluster-ip-range=169.169.0.0/16 \ # service虚拟IP地址范围 --service-node-port-range=30000-32767 \ # nodeport端口范围 --allow-privileged=true \ # 允许容器特权运行 --logtostderr=false --log-dir=/var/log/kubernetes --v=0" # --v日志级别,logtostderr表示不输出到stderr,可以输出到日志文件
3.6 创建客户端连接apisever 服务所需的kubeconfig文件
为控制器,调度器,kubelet,kubectl,kube-proxy统一创建一个kubeconfig文件连接到apiserver的配置文件。
将kubeconfig文件保存在/etc/kubernetes目录下。
apiVersion: v1 kind: Config clusters: - name: default cluster: server: https://192.168.18.100:9443 //vip地址和端口 certificate-authority: /etc/kubernetes/pki/ca.crt //根证书 user: - name: admin //名称和签发证书的名称一致,"/CN" user: client-certificate: /etc/kubernetes/pki/client.crt //为客户端签发的连接证书 client-key: /etc/kubernetes/pki/client.key //客户端私钥文件绝对路径 contexts: - context: cluster: default user: admin name: default current-context: default
四、部署kube-controller-manager
4.1 创建启动脚本
[Unit] Description=kuberbetes Controller-manager Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] EnvironmentFile=/etc/kubernetes/controller-manager ExecStart=/usr/bin/controller-manager $KUBE_CONTROLLER_MANAGER_ARGS Restart=always [Install] WantedBy=multi-user.target
4.2 配置文件 /etc/kubernetes/controller-manager 设置启动参数
KUBE_CONTROLLER_MANAGER_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \ --leader-elect=true \ //启动选举机制 --service-cluster-ip-range=169.169.0.0/16 \ //需要和APIserver保持一致 --service-account-private-key-file=/etc/kubernetes/pki/apiserver.key \ //为serviceAccount自动颁发Token使用的私钥路径 --root-ca-file=/etc/kubernetes/pki/ca.crt \ --log-dir=/var/log/kubernetes --logtostderr=false --v=0"
五、部署kube-scheduler服务
5.1 启动脚本
[Unit] Description=kuberbetes Scheduler Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] EnvironmentFile=/etc/kubernetes/scheduler ExecStart=/usr/bin/kube-schduler $KUBE_SCHDULER_ARGS Restart=always [Install] WantedBy=multi-user.target
5.2 配置文件对参数说明
KUBE_SCHEDULER_ARGS="--KUBECONFIG=/etc/kubernetes/kubeconfig \ //拿着APIServer签发的客户端证书和私钥访问 --leader-elect=true \ //启动选举 --logtostderr=false --log-dir=/var/log/kubernetes --v=0"
六、使用HAProxy和keepalived部署高可用负载均衡器
6.1 在3个apiserver前面部署负载均衡器,VIP作为客户访问入口。
frontend kube-apiserver mode tcp bind *:9443 option tcplog default_backend kube-apiserver .. backend kube-apiserver mode tcp balance roundrobin server k8s-master1 192.168.18.3:6443 check server k8s-master2 192.168.18.4:6443 check server k8s-master3 192.168.18.5:6443 check
6.2 在三台master服务器安装keepalived
global_defs {
router_id LVS_1 //按照实际填写
vrrp_script checkhaproxy { script "/usr/bin/check-haproxy.sh" interval 2 weight -30 } vrrp_instance VI_1 { //虚拟路由VRRP名称,名称必须一致,表示在同一个集群 state MASTER //其他为BACKUP interface ens33 //待设置VIP地址的网卡 virtual_router_id 51 //路由id priority 100 //优先级 advert_int 1 cirtual_ipaddress { 192.168.18.100/24 dev ens33 //VIP地址 } track_script { checkhaproxy //健康检查脚本 } }
将健康检测脚本定期执行
6.3 以容器方式运行keepalived,在18.3和18.4两台机器启动keepalived,将keepalived.conf文件挂载到容器内。
docker run -d --name k8s-keepalived --restart=always --net=host --cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW -v ${PWD}/keepalived.conf:/container/service/keepalived/assets/keepalived.conf -v ${PWD}/check-haproxy.sh:/usr/bin/check-haproxy.sh osixia/keepalived:2.0.20 --copy-service
七、部署Node服务
在Node节点需要部署docker,kubelet,kube-proxy,CNI网络插件,DNS插件等等。
7.1 部署kubelet
7.1.1 启动脚本
[Unit] Description=kuberbetes Kubelet Server Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] EnvironmentFile=/etc/kubernetes/kubelet ExecStart=/usr/bin/kubelet $KUBELET__ARGS Restart=always [Install] WantedBy=multi-user.target
7.1.2 配置文件/etc/kubernetes/kubelet对KUBELET_ARGS说明
KUBELET_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \ //需要复制相关客户端证书文件到node节点的/etc/kubernetes/pki目录下
--config=/etc/kubernetes/kubelet.conf \
--hostname-override=node1\ //node在集群中的名称,可以设置IP或域名
--network-plugin=cni \ //网络插件类型
--logtostderr=false --log-dir=/var/log/kubernetes --v=0"
7.1.3 kubelet.config内容
kind: KubeletConfiguration apiVersion: kubelet.config.k8s.io/v1beta1 adress: 0.0.0.0 //服务监听地址 port: 10250 cgroupDriver: cgroupfs //可选systend clusterDNS: ["169.168.0.100"] //集群DNS服务地址 clusterDomain: cluster.local //DNS后缀 authentication: //是否允许匿名访问或者webhook进行鉴权 anonymous: enabled: true
7.2 部署kube-proxy服务
7.2.1 启动脚本
[Unit] Description=kuberbetes Kube-Proxy Server Documentation=https://github.com/kubernetes/kubernetes After=network.target [Service] EnvironmentFile=/etc/kubernetes/proxy ExecStart=/usr/bin/kubelet $KUBE_PROXY_ARGS Restart=always [Install] WantedBy=multi-user.target
7.2.2 /etc/kubernetes/proxy
KUBE_PROXY_ARGS="--kubeconfig=/etc/kubernetes/kubeconfig \ --hostname=override=node2 \ --proxy-mode=iptables \ //包括ipvs --logtostderr=false --log-dir=/var/log/kubernetes --v=0"