内容简介:还是采用CentOS 7 版本系统,由于启用了 TLS 双向认证、RBAC 授权等严格的安全机制,建议从头开始部署,否则可能会认证、授权等失败!修改 /etc/fstab 文件,注释掉 SWAP 的自动挂载,使用free -m确认swap已经关闭。所有节点需要设定/etc/host解析到所有主机。
前排前排:
近期公司忙于重构,线上和线下均采用K8S,且均为高可用架构。为了日后便于分析问题,也为了开源的精神,故将此篇文章分享于此。(还是采用个人虚拟机,资源有限,但是服务的部署还是一一涵盖的!)
还是采用CentOS 7 版本系统,由于启用了 TLS 双向认证、RBAC 授权等严格的安全机制,建议从头开始部署,否则可能会认证、授权等失败!
一、组件版本 && 集群环境
组件版本
- Kubernetes 1.8.6
- Docker 17.10.0-ce
- Etcd 3.2.9
- Flanneld
- TLS 认证通信(所有组件,如etcd、kubernetes master 和node)
- RBAC 授权
- kubelet TLS Bootstrapping
- kubedns、dashboard、heapster等插件
- harbor,使用nfs后端存储
etcd 集群 && k8s master 机器 && k8s node 机器
IP Address | Role | 组件 |
---|---|---|
192.168.161.161 | master1 | etcd,kube-scheduler,kube-controller-manager,kube-apiserver |
192.168.161.162 | master2 | etcd,kube-scheduler,kube-controller-manager,kube-apiserver |
192.168.161.163 | master3 | etcd,kube-scheduler,kube-controller-manager,kube-apiserver |
192.168.161.164 | node1 | kube-proxy,kubelet,docker,flanneld |
192.168.161.165 | node2 | kube-proxy,kubelet,docker,flanneld |
192.168.161.200 | vip | api-server 高可用_ip |
首先安装前要确认以下几项都已将准备完成:
- 所有节点彼此网络互通,并且master1 SSH 登入其他节点为 passwdless。
- 所有防火墙与 SELinux 已关闭。如 CentOS:
# systemctl stop firewalld && systemctl disable firewalld && setenforce 0 && sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config
关闭Swap
swapoff -a sed 's/.*swap.*/#&/' /etc/fstab
修改 /etc/fstab 文件,注释掉 SWAP 的自动挂载,使用free -m确认swap已经关闭。
所有节点需要设定/etc/host解析到所有主机。
192.168.161.161 master1 192.168.161.162 master2 192.168.161.163 master3 192.168.161.164 node1 192.168.161.165 node2
所有节点需要设定/etc/sysctl.d/k8s.conf的系统参数。
# cat <<EOF > /etc/sysctl.d/k8s.conf net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF
加载br_netfilter
# modprobe br_netfilter # echo "modprobe br_netfilter" >> /etc/rc.local
刷新使之生效
# sysctl -p /etc/sysctl.d/k8s.conf
设置iptables策略为 ACCEPT
# /sbin/iptables -P FORWARD ACCEPT # echo "sleep 60 && /sbin/iptables -P FORWARD ACCEPT" >> /etc/rc.local
安装依赖包
# yum install -y epel-release # yum install -y yum-utils device-mapper-persistent-data lvm2 net-tools conntrack-tools wget
二、Kubernet 高可用集群搭建–创建证书
创建 CA 证书和秘钥
kubernetes 系统各组件需要使用 TLS 证书对通信进行加密,本文档使用 CloudFlare 的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 证书和秘钥文件,CA 是自签名的证书,用来签名后续创建的其它 TLS 证书。
生成的 CA 证书和秘钥文件如下:
ca-key.pem ca.pem kubernetes-key.pem kubernetes.pem kube-proxy.pem kube-proxy-key.pem admin.pem admin-key.pem
使用证书的组件如下:
- etcd:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
- kube-apiserver:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
- kubelet:使用 ca.pem;
- kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
- kubectl:使用 ca.pem、admin-key.pem、admin.pem;
- kube-controller-manager:使用 ca-key.pem、ca.pem
以下操作都在 master 节点即 192.168.161.161 上执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ 目录下的证书拷贝到新节点上即可
安装 CFSSL
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 chmod +x cfssl_linux-amd64 mv cfssl_linux-amd64 /usr/local/bin/cfssl wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x cfssljson_linux-amd64 mv cfssljson_linux-amd64 /usr/local/bin/cfssljson wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 chmod +x cfssl-certinfo_linux-amd64 mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo export PATH=/usr/local/bin:$PATH
创建 CA 配置文件
mkdir -p /etc/kubernetes/ssl && cd /etc/kubernetes/ssl
cat > ca-config.json << EOF { "signing": { "default": { "expiry": "8760h" }, "profiles": { "kubernetes": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "8760h" } } } } EOF
ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
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”:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
“O”:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
生成 CA 证书和私钥:
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca
创建 kubernetes 证书签名请求文件:
已经被坑过一次了,一定要把所有的机器都添加进去包括虚拟IP
添加IP地址的时候,需要想到有个域名转发的nginx server也需要添加如下
也就是说 当你后期扩容节点的时候,如果你这边没有写扩容节点的IP,是不可以扩容的。
cat > kubernetes-csr.json << EOF { "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.161.161", "192.168.161.162", "192.168.161.163", "192.168.161.200", "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" } ] } EOF如上4个ip替换成自己服务器的ip。
hosts 中的内容可以为空,即使按照上面的配置,向集群中增加新节点后也不需要重新生成证书。
如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表 ,由于该证书后续被 etcd 集群和 kubernetes master 集群使用,所以上面分别指定了 etcd 集群、kubernetes master 集群的主机 IP 和 kubernetes 服务的服务 IP (一般是 kue-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.254.0.1。
生成 kubernetes 证书和私钥
# 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
创建 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
- 后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
- kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Groupsystem:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 的 所有API的权限 ;
- OU 指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的system:masters,所以被授予访问所有 API 的权限;
生成 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
创建 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-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
生成 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
校验证书
以 kubernetes 证书为例
使用 Opsnssl 命令
$ openssl x509 -noout -text -in kubernetes.pem ... Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=Kubernetes Validity Not Before: Apr 5 05:36:00 2017 GMT Not After : Apr 5 05:36:00 2018 GMT Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes ... X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: DD:52:04:43:10:13:A9:29:24:17:3A:0E:D7:14:DB:36:F8:6C:E0:E0 X509v3 Authority Key Identifier: keyid:44:04:3B:60:BD:69:78:14:68:AF:A0:41:13:F6:17:07:13:63:58:CD X509v3 Subject Alternative Name: DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.default.svc.cluster.local, IP Address:127.0.0.1, IP Address:172.20.0.112, IP Address:172.20.0.113, IP Address:172.20.0.114, IP Address:172.20.0.115, IP Address:10.254.0.1 ...
- 确认 Issuer 字段的内容和 ca-csr.json 一致;
- 确认 Subject 字段的内容和 kubernetes-csr.json 一致;
- 确认 X509v3 Subject Alternative Name 字段的内容和 kubernetes-csr.json 一致;
- 确认 X509v3 Key Usage、Extended Key Usage 字段的内容和 ca-config.json 中 kubernetesprofile 一致;
使用 Cfssl-Certinfo 命令
$ cfssl-certinfo -cert kubernetes.pem ... { "subject": { "common_name": "kubernetes", "country": "CN", "organization": "k8s", "organizational_unit": "System", "locality": "BeiJing", "province": "BeiJing", "names": [ "CN", "BeiJing", "BeiJing", "k8s", "System", "kubernetes" ] }, "issuer": { "common_name": "Kubernetes", "country": "CN", "organization": "k8s", "organizational_unit": "System", "locality": "BeiJing", "province": "BeiJing", "names": [ "CN", "BeiJing", "BeiJing", "k8s", "System", "Kubernetes" ] }, "serial_number": "174360492872423263473151971632292895707129022309", "sans": [ "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster", "kubernetes.default.svc.cluster.local", "127.0.0.1", "10.64.3.7", "10.254.0.1" ], "not_before": "2018-06-05T05:36:00Z", "not_after": "2019-06-05T05:36:00Z", "sigalg": "SHA256WithRSA", ...
分发证书
将生成的证书和秘钥文件(后缀名为.pem)拷贝到所有master和node节点的 /etc/kubernetes/ssl 目录下:
需要在所有的机器上面创建/etc/kubernetes/ssl目录:
$ mkdir -p /etc/kubernetes/ssl $ cp *.pem /etc/kubernetes/ssl master1: $ scp *.pem 192.168.161.162:/etc/kubernetes/ssl $ scp *.pem 192.168.161.163:/etc/kubernetes/ssl $ scp *.pem 192.168.161.164:/etc/kubernetes/ssl $ scp *.pem 192.168.161.165:/etc/kubernetes/ssl
三、Kubernet 高可用集群搭建–Etcd集群
在三个节点都安装etcd,下面的操作需要在三个节点都执行一遍
下载etcd安装包
# wget https://github.com/coreos/etcd/releases/download/v3.2.12/etcd-v3.2.12-linux-amd64.tar.gz # tar -xvf etcd-v3.2.12-linux-amd64.tar.gz # sudo mv etcd-v3.2.12-linux-amd64/etcd* /usr/local/bin
创建工作目录
mkdir -p /var/lib/etcd (根据实际业务场景,修改数据盘位置)
创建systemd unit 文件
当然 在其它两台机器上面的地址需要更改为另外两台机器的IP。
cat > etcd.service << EOF [Unit] Description=Etcd Server After=network.target After=network-online.target Wants=network-online.target Documentation=https://github.com/coreos [Service] Type=notify WorkingDirectory=/var/lib/etcd/ ExecStart=/usr/local/bin/etcd \\ --name master1 \\ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\ --initial-advertise-peer-urls https://192.168.161.161:2380 \\ --listen-peer-urls https://192.168.161.161:2380 \\ --listen-client-urls https://192.168.161.161:2379,http://127.0.0.1:2379 \\ --advertise-client-urls https://192.168.161.161:2379 \\ --initial-cluster-token etcd-cluster-0 \\ --initial-cluster master1=https://192.168.161.161:2380,master2=https://192.168.161.162:2380,master3=https://192.168.161.163:2380 \\ --initial-cluster-state new \\ --data-dir=/var/lib/etcd Restart=on-failure RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF如上的IP地址192.168.161.XXX 请逐一替换成你自己服务器的IP。
不要忽略name
下面给出常用配置的参数和它们的解释,方便理解:
--name:方便理解的节点名称,默认为 default,在集群中应该保持唯一,可以使用 hostname --data-dir:服务运行数据保存的路径,默认为 ${name}.etcd --snapshot-count:指定有多少事务(transaction)被提交时,触发截取快照保存到磁盘 --heartbeat-interval:leader 多久发送一次心跳到 followers。默认值是 100ms --eletion-timeout:重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票,默认为 1000 ms --listen-peer-urls:和同伴通信的地址,比如 http://ip:2380,如果有多个,使用逗号分隔。需要所有节点都能够访问,所以不要使用 localhost! --listen-client-urls:对外提供服务的地址:比如 http://ip:2379,http://127.0.0.1:2379,客户端会连接到这里和 etcd 交互 --advertise-client-urls:对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点 --initial-advertise-peer-urls:该节点同伴监听地址,这个值会告诉集群中其他节点 --initial-cluster:集群中所有节点的信息,格式为 node1=http://ip1:2380,node2=http://ip2:2380,…。注意:这里的 node1 是节点的 --name 指定的名字;后面的 ip1:2380 是 --initial-advertise-peer-urls 指定的值 --initial-cluster-state:新建集群的时候,这个值为 new;假如已经存在的集群,这个值为 existing --initial-cluster-token:创建集群的 token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误
所有以 –init 开头的配置都是在 bootstrap 集群的时候才会用到,后续节点的重启会被忽略。
NOTE:所有的参数也可以通过环境变量进行设置,–my-flag 对应环境变量的 ETCD_MY_FLAG;但是命令行指定的参数会覆盖环境变量对应的值。
指定 etcd 的工作目录为 /var/lib/etcd,数据目录为 /var/lib/etcd,需在启动服务前创建这个目录,否则启动服务的时候会报错“Failed at step CHDIR spawning /usr/bin/etcd: No such file or directory”;
为了保证通信安全,需要指定 etcd 的公私钥(cert-file和key-file)、Peers 通信的公私钥和 CA 证书(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客户端的CA证书(trusted-ca-file);
创建 kubernetes.pem 证书时使用的 kubernetes-csr.json 文件的 hosts 字段包含所有 etcd 节点的IP,否则证书校验会出错;
–initial-cluster-state 值为 new 时,–name 的参数值必须位于 –initial-cluster 列表中;
启动 etcd 服务
cp etcd.service /etc/systemd/system/ systemctl daemon-reload systemctl enable etcd systemctl start etcd systemctl status etcd最先启动的 etcd 进程会卡住一段时间,等待其它节点上的 etcd 进程加入集群,为正常现象。
如上操作请确认一定要在三台机器上面都要执行;(单节点ETCD除外)
验证etcd服务,在任何一个etcd节点执行:
如果不添加密钥参数是会报错的:
[root@master1 ssl]# etcdctl cluster-health failed to check the health of member 1d6f3edf4016ed5d on https://192.168.161.163:2379: Get https://192.168.161.163:2379/health: x509: certificate signed by unknown authority member 1d6f3edf4016ed5d is unreachable: [https://192.168.161.163:2379] are all unreachable failed to check the health of member 3d9715816751f109 on https://192.168.161.162:2379: Get https://192.168.161.162:2379/health: x509: certificate signed by unknown authority member 3d9715816751f109 is unreachable: [https://192.168.161.162:2379] are all unreachable failed to check the health of member d5fabdfaee58386c on https://192.168.161.161:2379: Get https://192.168.161.161:2379/health: x509: certificate signed by unknown authority member d5fabdfaee58386c is unreachable: [https://192.168.161.161:2379] are all unreachable cluster is unhealthy
使用密钥方式检查集群状态
[root@master1 ssl]# etcdctl \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ cluster-health member 1d6f3edf4016ed5d is healthy: got healthy result from https://192.168.161.163:2379 member 3d9715816751f109 is healthy: got healthy result from https://192.168.161.162:2379 member d5fabdfaee58386c is healthy: got healthy result from https://192.168.161.161:2379 cluster is healthy
部署 Flannel
在三个节点都安装Flannel,下面的操作需要在 三个节点都执行一遍
下载安装Flannel
# wget https://github.com/coreos/flannel/releases/download/v0.9.1/flannel-v0.9.1-linux-amd64.tar.gz # mkdir flannel # tar -xzvf flannel-v0.9.1-linux-amd64.tar.gz -C flannel # cp flannel/{flanneld,mk-docker-opts.sh} /usr/local/bin
向 etcd 写入网段信息, 这两个命令只需要任意一个节点上执行一次就可以
etcdctl --endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ mkdir /kubernetes/network etcdctl --endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \ --ca-file=/etc/kubernetes/ssl/ca.pem \ --cert-file=/etc/kubernetes/ssl/kubernetes.pem \ --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \ mk /kubernetes/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'
注意如上更换成自己的IP
创建systemd unit 文件 在 node机器上 面都需要执行
cat > flanneld.service << EOF [Unit] Description=Flanneld overlay address etcd agent After=network.target After=network-online.target Wants=network-online.target After=etcd.service Before=docker.service [Service] Type=notify ExecStart=/usr/local/bin/flanneld \\ -etcd-cafile=/etc/kubernetes/ssl/ca.pem \\ -etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \\ -etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \\ -etcd-endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \\ -etcd-prefix=/kubernetes/network ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure [Install] WantedBy=multi-user.target RequiredBy=docker.service EOF
mk-docker-opts.sh 脚本将分配给 flanneld 的 Pod 子网网段信息写入到 /run/flannel/docker 文件中,后续 docker 启动时使用这个文件中参数值设置 docker0 网桥;
flanneld 使用系统缺省路由所在的接口和其它节点通信,对于有多个网络接口的机器(如,内网和公网),可以用 -iface=enpxx 选项值指定通信接口;
启动Flannel
mv flanneld.service /etc/systemd/system/ systemctl daemon-reload systemctl enable flanneld systemctl start flanneld systemctl status flanneld
检查flannel服务状态
[root@master1 src]# /usr/local/bin/etcdctl --endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 --ca-file=/etc/kubernetes/ssl/ca.pem --cert-file=/etc/kubernetes/ssl/kubernetes.pem --key-file=/etc/kubernetes/ssl/kubernetes-key.pem ls /kubernetes/network/subnets /kubernetes/network/subnets/172.30.68.0-24 /kubernetes/network/subnets/172.30.46.0-24
四、Kubernet 高可用集群搭建–kubectl
部署 kubectl 工具,创建kubeconfig文件
kubectl是kubernetes的集群管理工具,任何节点通过kubetcl都可以管理整个k8s集群。
本文是在 master节点 部署,部署成功后会生成 /root/.kube/config 文件,kubectl就是通过这个获取 kube-apiserver 地址、证书、用户名等信息,所以这个文件需要保管好。
下载安装包
# cd /usr/local/src # wget https://dl.k8s.io/v1.8.6/kubernetes-client-linux-amd64.tar.gz # tar -xzvf kubernetes-client-linux-amd64.tar.gz # sudo cp kubernetes/client/bin/kube* /usr/local/bin/ # chmod a+x /usr/local/bin/kube* # export PATH=/usr/local/bin:$PATH
创建/root/.kube/config
# 设置集群参数,--server指定VIP的ip kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.161.200:6443 # 设置客户端认证参数 kubectl config set-credentials admin \ --client-certificate=/etc/kubernetes/ssl/admin.pem \ --embed-certs=true \ --client-key=/etc/kubernetes/ssl/admin-key.pem # 设置上下文参数 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=admin # 设置默认上下文 kubectl config use-context kubernetes注意:如上是注解,标注是后期更清晰些
。
admin.pem 证书 O 字段值为 system:masters,kube-apiserver 预定义的 RoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 相关 API 的权限
创建bootstrap.kubeconfig
kubelet访问kube-apiserver的时候是通过bootstrap.kubeconfig进行用户验证。
//生成token 变量 # 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" EOF
分发 token.csv 文件
将 token.csv 文件拷贝到所有Master 和 Node的 /etc/kubernetes/ 目录: $ cp token.csv /etc/kubernetes/ master01: $ scp /etc/kubernetes/token.csv 192.168.161.162:/etc/kubernetes/ $ scp /etc/kubernetes/token.csv 192.168.161.163:/etc/kubernetes/ $ scp /etc/kubernetes/token.csv 192.168.161.164:/etc/kubernetes/ $ scp /etc/kubernetes/token.csv 192.168.161.165:/etc/kubernetes/ //设置集群参数--server为VIP节点ip # kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.161.200:6443 \ --kubeconfig=bootstrap.kubeconfig //设置客户端认证参数 # kubectl config set-credentials kubelet-bootstrap \ --token=${BOOTSTRAP_TOKEN} \ --kubeconfig=bootstrap.kubeconfig //设置上下文参数 # kubectl config set-context default \ --cluster=kubernetes \ --user=kubelet-bootstrap \ --kubeconfig=bootstrap.kubeconfig //设置默认上下文 # kubectl config use-context default --kubeconfig=bootstrap.kubeconfig # cp bootstrap.kubeconfig /etc/kubernetes/
创建kube-proxy.kubeconfig
# 设置集群参数 --server参数为 VIP的 ip kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=https://192.168.161.200:6443 \ --kubeconfig=kube-proxy.kubeconfig # 设置客户端认证参数 kubectl config set-credentials kube-proxy \ --client-certificate=/etc/kubernetes/ssl/kube-proxy.pem \ --client-key=/etc/kubernetes/ssl/kube-proxy-key.pem \ --embed-certs=true \ --kubeconfig=kube-proxy.kubeconfig # 设置上下文参数 kubectl config set-context default \ --cluster=kubernetes \ --user=kube-proxy \ --kubeconfig=kube-proxy.kubeconfig //设置默认上下文 # kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig # cp kube-proxy.kubeconfig /etc/kubernetes/
设置集群参数和客户端认证参数时 –embed-certs 都为 true,这会将 certificate-authority、client-certificate 和 client-key 指向的证书文件内容写入到生成的 kube-proxy.kubeconfig 文件中;
kube-proxy.pem 证书中 CN 为 system:kube-proxy,kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
分发 kubeconfig
将两个 kubeconfig 文件拷贝到所有 的 节点的 /etc/kubernetes/ 目录:
master01: $ scp /etc/kubernetes/*.kubeconfig 192.168.161.164:/etc/kubernetes/ $ scp /etc/kubernetes/*.kubeconfig 192.161.161.165:/etc/kubernetes/
分发 kubeconfig 文件
将 ~/.kube/config 文件拷贝到运行 kubectl 命令的机器的 ~/.kube/ 目录下。 其它所有master和node节点创建目录: $ mkdir -p /root/.kube master01: $ scp ~/.kube/config 192.168.161.162:/root/.kube $ scp ~/.kube/config 192.168.161.163:/root/.kube $ scp ~/.kube/config 192.168.161.164:/root/.kube $ scp ~/.kube/config 192.168.161.165:/root/.kube
五、Kubernet 高可用集群搭建–master安装组件
下载安装文件
# wget https://dl.k8s.io/v1.8.6/kubernetes-server-linux-amd64.tar.gz # tar -xzvf kubernetes-server-linux-amd64.tar.gz # cp -r kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin/
配置和启动 kube-apiserver(两台master,master2上面直接修改master2的IP即可)
cat > kube-apiserver.service << EOF [Unit] Description=Kubernetes API Server Documentation=https://github.com/GoogleCloudPlatform/kubernetes After=network.target After=etcd.service [Service] ExecStart=/usr/local/bin/kube-apiserver \\ --logtostderr=true \\ --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,NodeRestriction \\ --advertise-address=192.168.161.161 \\ --bind-address=0.0.0.0 \\ --insecure-bind-address=0.0.0.0 \\ --authorization-mode=Node,RBAC \\ --runtime-config=rbac.authorization.k8s.io/v1alpha1 \\ --kubelet-https=true \\ --enable-bootstrap-token-auth \\ --token-auth-file=/etc/kubernetes/token.csv \\ --service-cluster-ip-range=10.254.0.0/16 \\ --service-node-port-range=8400-10000 \\ --tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\ --tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\ --client-ca-file=/etc/kubernetes/ssl/ca.pem \\ --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \\ --etcd-cafile=/etc/kubernetes/ssl/ca.pem \\ --etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \\ --etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \\ --etcd-servers=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \\ --enable-swagger-ui=true \\ --allow-privileged=true \\ --apiserver-count=3 \\ --audit-log-maxage=30 \\ --audit-log-maxbackup=3 \\ --audit-log-maxsize=100 \\ --audit-log-path=/var/lib/audit.log \\ --event-ttl=1h \\ --v=2 Restart=on-failure RestartSec=5 Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
注意 更换成自己的IP
–authorization-mode=RBAC 指定在安全端口使用 RBAC 授权模式,拒绝未通过授权的请求; kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信; kubelet、kube-proxy、kubectl 部署在其它 Node 节点上,如果通过安全端口访问 kube-apiserver,则必须先通过 TLS 证书认证,再通过 RBAC 授权; kube-proxy、kubectl 通过在使用的证书里指定相关的 User、Group 来达到通过 RBAC 授权的目的; 如果使用了 kubelet TLS Boostrap 机制,则不能再指定 –kubelet-certificate-authority、–kubelet-client-certificate 和 –kubelet-client-key 选项,否则后续 kube-apiserver 校验 kubelet 证书时出现 ”x509: certificate signed by unknown authority“ 错误; –admission-control 值必须包含 ServiceAccount,否则部署集群插件时会失败; –bind-address 不能为 127.0.0.1; –runtime-config配置为rbac.authorization.k8s.io/v1beta1,表示运行时的apiVersion; –service-cluster-ip-range 指定 Service Cluster IP 地址段,该地址段不能路由可达; –service-node-port-range 指定 NodePort 的端口范围; 缺省情况下 kubernetes 对象保存在 etcd /registry 路径下,可以通过 –etcd-prefix 参数进行调整;
启动 kube-apiserver
# cp kube-apiserver.service /etc/systemd/system/ systemctl daemon-reload systemctl enable kube-apiserver systemctl start kube-apiserver systemctl status kube-apiserver
部署kube-apiserver 高可用
安装haproxy
$ yum install -y haproxy
配置haproxy
由于集群内部有的组建是通过非安全端口访问apiserver 的,有的是通过安全端口访问apiserver 的,所以我们要配置http 和https 两种代理方式,配置文件 /etc/haproxy/haproxy.cfg:( Master1和Master2上直接Copy此配置即可: )
listen stats bind *:9000 mode http stats enable stats hide-version stats uri /stats stats refresh 30s stats realm Haproxy\ Statistics stats auth Admin:Password frontend k8s-api bind 192.168.161.200:6443 mode tcp option tcplog tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } default_backend k8s-api backend k8s-api mode tcp option tcplog option tcp-check balance roundrobin default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100 server k8s-api-1 192.168.161.161:6443 check server k8s-api-2 192.168.161.162:6443 check frontend k8s-http-api bind 192.168.161.200:8080 mode tcp option tcplog default_backend k8s-http-api backend k8s-http-api mode tcp option tcplog option tcp-check balance roundrobin default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100 server k8s-http-api-1 192.168.161.161:8080 check server k8s-http-api-2 192.168.161.162:8080 check
通过上面的配置文件我们可以看出通过https的访问将请求转发给apiserver 的6443端口了,http的请求转发到了apiserver 的8080端口。
启动haproxy
systemctl start haproxy systemctl enable haproxy systemctl status haproxy
然后我们可以通过上面9000端口监控我们的haproxy的运行状态(192.168.161.161:9000/stats):
上面我们的haproxy的确可以代理我们的两个master 上的apiserver 了,但是还不是高可用的,如果master01 这个节点down 掉了,那么我们haproxy 就不能正常提供服务了。这里我们可以使用两种方法来实现高可用
方式1:使用阿里云SLB(我们线上用的方式)
这种方式实际上是最省心的,在阿里云上建一个内网的SLB,将master01 与master02 添加到SLB 机器组中,转发80(http)和443(https)端口即可(注意下面的提示)
注意:阿里云的负载均衡是四层TCP负责,不支持后端ECS实例既作为Real Server又作为客户端向所在的负载均衡实例发送请求。因为返回的数据包只在云服务器内部转发,不经过负载均衡,所以在后端ECS实例上去访问负载均衡的服务地址是不通的。什么意思?就是如果你要使用阿里云的SLB的话,那么你不能在apiserver节点上使用SLB(比如在apiserver 上安装kubectl,然后将apiserver的地址设置为SLB的负载地址使用),因为这样的话就可能造成回环了,所以简单的做法是另外用两个新的节点做HA实例,然后将这两个实例添加到SLB 机器组中。
方式2:使用keepalived
KeepAlived 是一个高可用方案,通过 VIP(即虚拟 IP)和心跳检测来实现高可用。其原理是存在一组(两台)服务器,分别赋予 Master、Backup 两个角色,默认情况下Master 会绑定VIP 到自己的网卡上,对外提供服务。Master、Backup 会在一定的时间间隔向对方发送心跳数据包来检测对方的状态,这个时间间隔一般为 2 秒钟,如果Backup 发现Master 宕机,那么Backup 会发送ARP 包到网关,把VIP 绑定到自己的网卡,此时Backup 对外提供服务,实现自动化的故障转移,当Master 恢复的时候会重新接管服务。非常类似于路由器中的虚拟路由器冗余协议(VRRP)
开启路由转发,这里我们定义虚拟IP为: 192.168.161.200
$ vim /etc/sysctl.conf # 添加以下内容 net.ipv4.ip_forward = 1 net.ipv4.ip_nonlocal_bind = 1 # 验证并生效 $ sysctl -p # 验证是否生效 $ cat /proc/sys/net/ipv4/ip_forward 1
安装keepalived:
$ yum install -y keepalived
我们这里将master1 设置为Master,master2 设置为Backup,修改配置:
vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { } router_id kube_api } vrrp_script check_k8s { # 自身状态检测 script "/etc/keepalived/chk_k8s_master.sh" interval 3 weight 5 } vrrp_instance haproxy-vip { # 使用单播通信,默认是组播通信 unicast_src_ip 192.168.161.161 unicast_peer { 192.168.161.162 } # 初始化状态 state BACKUP # 虚拟ip 绑定的网卡 interface ens33 # 此ID 要与Backup 配置一致 virtual_router_id 51 # 默认启动优先级,要比Backup 大点,但要控制量,保证自身状态检测生效 priority 99 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { # 虚拟ip 地址 192.168.161.200/24 } track_script { check_k8s } }
自身状态监测脚本,这里通过 api-server 是否在监听端口(6433 端口)来判断状态。
#!/bin/bash d=`date --date today +%Y%m%d_%H:%M:%S` n=`ps -C kube-apiserver --no-heading|wc -l` if [ $n -eq "0" ]; then systemctl start kube-apiserver n2=`ps -C kube-apiserver --no-heading|wc -l` if [ $n2 -eq "0" ]; then echo "$d Kube-apiserver down,keepalived will stop" >> /var/log/check_ng.log systemctl stop keepalived fi fi
统一的方式 在master02 节点上安装keepalived,修改配置,只需要将state 更改成BACKUP,priority更改成99,unicast_src_ip 与unicast_peer 地址修改即可。
启动keepalived:
$ systemctl start keepalived $ systemctl enable keepalived # 查看日志 $ journalctl -f -u keepalived
查看IP
[root@master1 keepalived]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:26:e9:ae brd ff:ff:ff:ff:ff:ff inet 192.168.161.161/24 brd 192.168.161.255 scope global ens33 valid_lft forever preferred_lft forever inet 192.168.161.200/24 scope global secondary ens33 valid_lft forever preferred_lft forever inet6 fe80::2e63:8644:7484:a297/64 scope link valid_lft forever preferred_lft forever
六、Kubernet 高可用集群搭建–Master组件
配置和启动 kube-controller-manager
scheduler,controller-manager在集群中只能在一台主机开启,这里我们可以在启动controller-manager和scheduler 只要加上 –leader-elect=true 参数就可以同时启动,系统会自动选举leader。3台master部署controller-manager,以master1为例,替换各master的ip地址,serviceip范围和pod可获取的ip范围
cat > kube-controller-manager.service << EOF [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] ExecStart=/usr/local/bin/kube-controller-manager \ --logtostderr=true \ --address=127.0.0.1 \ --master=https://192.168.161.200:6443 \ --allocate-node-cidrs=true \ --service-cluster-ip-range=10.254.0.0/16 \ --cluster-cidr=172.30.0.0/16 \ --cluster-name=kubernetes \ --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \ --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \ --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \ --root-ca-file=/etc/kubernetes/ssl/ca.pem \ --leader-elect=true \ --v=2 Restart=on-failure LimitNOFILE=65536 RestartSec=5 [Install] WantedBy=multi-user.target EOF
启动 kube-controller-manager
# cp kube-controller-manager.service /etc/systemd/system/ # systemctl daemon-reload # systemctl enable kube-controller-manager # systemctl start kube-controller-manager
三台部署scheduler,以master01为例,替换各master的ip地址
cat > kube-scheduler.service << EOF [Unit] Description=Kubernetes Scheduler Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] ExecStart=/usr/local/bin/kube-scheduler \\ --logtostderr=true \\ --address=127.0.0.1 \\ --master=https://192.168.161.200:6443 \\ --leader-elect=true \\ --v=2 Restart=on-failure LimitNOFILE=65536 RestartSec=5 [Install] WantedBy=multi-user.target EOF
启动 kube-scheduler
# cp kube-scheduler.service /etc/systemd/system/ # systemctl daemon-reload # systemctl enable kube-scheduler # systemctl start kube-scheduler
kube-controller-manager 和kube-scheduler 的高可用
Kubernetes 的管理层服务包括kube-scheduler和kube-controller-manager。kube-scheduler和kube-controller-manager使用一主多从的高可用方案, 在同一时刻只允许一个服务处以具体的任务 。Kubernetes中实现了一套简单的选主逻辑,依赖Etcd实现scheduler和controller-manager的选主功能。如果scheduler和controller-manager在启动的时候设置了 leader-elect参数 ,它们在启动后会先尝试获取leader节点身份,只有在获取leader节点身份后才可以执行具体的业务逻辑。它们分别会在Etcd中创建kube-scheduler和kube-controller-manager的endpoint,endpoint的信息中记录了当前的leader节点信息,以及记录的上次更新时间。leader节点会定期更新endpoint的信息,维护自己的leader身份。每个从节点的服务都会定期检查endpoint的信息,如果endpoint的信息在时间范围内没有更新,它们会尝试更新自己为leader节点。scheduler服务以及controller-manager服务之间不会进行通信,利用Etcd的强一致性,能够保证在分布式高并发情况下leader节点的全局唯一性。整体方案如下图所示:
当集群中的leader节点服务异常后,其它节点的服务会尝试更新自身为leader节点,当有多个节点同时更新endpoint时,由Etcd保证只有一个服务的更新请求能够成功。通过这种机制sheduler和controller-manager可以保证在leader节点宕机后其它的节点可以顺利选主,保证服务故障后快速恢复。当集群中的网络出现故障时对服务的选主影响不是很大, 因为scheduler和controller-manager是依赖Etcd进行选主的 ,在网络故障后,可以和Etcd通信的主机依然可以按照之前的逻辑进行选主,就算集群被切分,Etcd也可以保证同一时刻只有一个节点的服务处于leader状态。
验证 master 节点功能
Master1 上面:
[root@master1 ~]# kubectl get cs NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health": "true"} etcd-2 Healthy {"health": "true"} etcd-1 Healthy {"health": "true"}
Master2 上面:
[root@master2 ~]# kubectl get cs NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health": "true"} etcd-2 Healthy {"health": "true"} etcd-1 Healthy {"health": "true"}
以上所述就是小编给大家介绍的《Kubernet 高可用集群搭建(上)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Elasticsearch 集群搭建和集群原理
- Zookeeper学习系列【二】Zookeeper 集群章节之集群搭建
- Spark集群环境搭建
- Zookeeper搭建集群
- FastDFS集群搭建
- Zookeeper集群环境搭建
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP Web 2.0开发实战
泽瓦斯 / 苏金国 / 人民邮电出版社 / 2008-10-1 / 59.00元
本书通过一个完整的Web 2.0应用——带有动态图库、搜索和地图功能的博客系统详细介绍了Web开发的全过程。首先讨论了Web应用的规划与设计,然后逐章实现各个具体特性,包括网站主页、用户主页、用户注册页面、账户登录和管理页面、用户博客系统、网站搜索以及应用管理等,最后介绍部署和维护。 本书适合中、高级的PHP程序员阅读。一起来看看 《PHP Web 2.0开发实战》 这本书的介绍吧!