K8s简介
Kubernetes(简称k8s)是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了资源调度、部署管理、服务发现、扩容缩容、监控,维护等一整套功能。,努力成为跨主机集群的自动部署、扩展以及运行应用程序容器的平台。 它支持一系列容器工具, 包括Docker等。
# kubernetes
注意 本文所有操作均在所有节点执行 本文环境
名称
配置
Kubernetes版本
v1.17.3
Cluster Pod CIDR
10.244.0.0/16
Cluster Service CIDR
10.250.0.0/24
kubernetes service
10.250.0.1
dns service
10.250.0.10
本文档主要介绍在裸机环境下以二进制的方式安装部署kubernetes
本次文档主要是对于kubernetes 1.17.3版本
内容主要有环境准备安装配置docker 升级内核 调整系统参数
环境准备
主机名
IP
组件
配置
k8s-master1
192.168.220.101
apiserver、controller-manager、schedule、docker-ce
2核 4G
k8s-master2
192.168.220.102
apiserver、controller-manager、schedule、docker-ce
2核 4G
k8s-node1
192.168.220.103
kube-proxy、kubelet、docker-ce,etcd
2核 4G
k8s-node1
192.168.220.104
kube-proxy、kubelet、docker-ce,etcd
2核 4G
k8s-node1
192.168.220.105
kube-proxy、kubelet、docker-ce,etcd
2核 4G
以下操作除非具体说明的步骤 其他的均在所有节点执行
环境变量 此环境变量为主节点(控制节点)的主机名和IP地址
1 2 3 4 5 6 7 8 9 10 11 export VIP=192.168.220.100export MASTER1_HOSTNAME=k8s-master1export MASTER1_IP=192.168.220.101export MASTER2_HOSTNAME=k8s-master2export MASTER2_IP=192.168.220.102export NODE1_HOSTNAME=k8s-node1export NODE1_IP=192.168.220.103export NODE1_HOSTNAME=k8s-node2export NODE1_IP=192.168.220.104export NODE1_HOSTNAME=k8s-node3export NODE1_IP=192.168.220.105
SSH免密/时间同步/主机名修改 · SSH免密
· NTP时间同步
· 主机名修改
· 环境变量生成
· Host 解析
这里需要说一下,所有的密钥分发以及后期拷贝等都在master1上操作,因为master1做免密了
k8s集群所有的机器都需要进行host解析
1 2 3 4 5 6 7 cat >> /etc/hosts << EOF 192.168.220.101 k8s-master1192.168.220.102 k8s-master2192.168.220.103 k8s-node1192.168.220.104 k8s-node2192.168.220.105 k8s-node3EOF
批量免密
# 做免密前请修改好主机名对应的host
1 2 3 4 5 6 7 8 9 10 11 yum - y install expect ssh- keygen - t rsa - P "" - f / root/ .ssh/ id_rsa for i in 192.168 .220.101 192.168 .220.102 192.168 .220.103 192.168 .220.104 192.168 .220.105 ;do expect - c " spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$i expect { \" *yes/no*\" {send \" yes\r \" ; exp_continue} \" *password*\" {send \" quhuixx\r \" ; exp_continue} \" *Password*\" {send \" quhuixx\r \" ;} } " done
切记所有机器需要自行设定ntp,否则不只HA下apiserver通信有问题,各种千奇百怪的问题。
1 2 3 4 5 6 yum -y install ntp systemctl enable ntpd systemctl start ntpd ntpdate -u time1 .aliyun .com hwclock --systohc timedatectl set-timezone Asia /Shanghai
测试通信
1 for i in k8s-master1 k8s-master2 k8s-node1 k8s-node2 k8s-node3; do ssh root@$i "hostname" ;done
升级内核 安装内核语言编译器(内核是用perl语言编写的)
下载密钥和yum源
导入密钥
安装7版本的yum源文件
1 yum -y install https://www.elrepo.org/elrepo-release-7 .0 -4 .el7.elrepo.noarch.rpm
安装 ml版本 5版本的内核名字叫ml
1 yum --enablerepo= "elrepo-kernel" -y install kernel-ml.x86_64
附:4.4版本内核安装方法
1 yum --enablerepo= "elrepo-kernel" -y install kernel-lt.x86_64
然后配置从新的内核启动
然后重新生成grub2.cfg 使虚拟机使用新内核启动
1 grub2-mkconfig -o /boot/g rub2/grub.cfg
调整系统内核参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 cat > /etc/sysctl.conf <<EOF net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-call-ip6tables=1 net.ipv4.ip_forward=1 vm.swappiness=0 vm.overcommit_memory=1 vm.panic_on_oom=0 fs.inotify.max_user_instances=8192 fs.inotify.max_user_watches=1048576 fs.file-max=52706963 fs.nr_open=52706963 net.ipv6.conf.all.disable_ipv6=1 net.netfilter.nf_conntrack_max=2310720 EOF
然后执行sysctl -p 使配置的内核响应参数生效
关闭防火墙、selinux、swap、NetworkManager 1 2 3 4 5 6 7 8 9 systemctl stop firewalld systemctl disable firewalld iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat iptables -P FORWARD ACCEPT sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab setenforce 0 sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config systemctl stop NetworkManager systemctl disable NetworkManager
修改资源限制 1 2 3 4 5 6 echo "* soft nofile 65536" >> /etc/security/limits.conf echo "* hard nofile 65536" >> /etc/security/limits.conf echo "* soft nproc 65536" >> /etc/security/limits.conf echo "* hard nproc 65536" >> /etc/security/limits.conf echo "* soft memlock unlimited" >> /etc/security/limits.conf echo "* hard memlock unlimited" >> /etc/security/limits.conf
常用软件安装 1 yum -y install bridge-utils chrony ipvsadm ipset sysstat conntrack libseccomp wget tcpdump screen vim nfs-utils bind-utils wget socat telnet sshpass net-tools sysstat lrzsz yum-utils device-mapper-persistent-data lvm2 tree nc lsof strace nmon iptraf iftop rpcbind mlocate ipvsadm
加载内核ipvs模块 1 2 3 4 5 6 7 8 9 10 11 12 13 cat > /etc/sysconfig/modules/ipvs.modules <<EOF # !/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack_ipv4 EOF chmod 755 /etc/sysconfig/modules/ipvs.modules bash /etc/sysconfig/modules/ipvs.modules lsmod | grep -e ip_vs -e nf_conntrack_ipv4
安装docker-ce: 添加yun源
1 2 3 4 5 6 7 8 tee /etc/yum .repos.d/docker-ce.repo <<-'EOF' [aliyun-docker-ce] name=aliyun-docker-ce baseurl=https://mi rrors.aliyun.com/docker-ce/ linux/centos/ 7 /x86_64/ stable/ enable=1 gpgcheck=1 gpgkey=https://mi rrors.aliyun.com/docker-ce/ linux/centos/g pg EOF
安装docker-ce
1 yum -y install docker-ce
重启docker并设置为开机自启
1 2 3 system ctl daemon-reloadsystem ctl restart dockersystem ctl enable docker
然后重启系统 验证内核是否升级成功 下载命令 下载cfssl以及cfssljson命令 此举目的是下载创建证书以及配置文件需要的命令
PKI基础概念
什么是PKI?
公开密钥基础建设(英语:Public Key Infrastructure,缩写:PKI),又称公开密钥基础架构、公钥基础建设、公钥基础设施、公开密码匙基础建设或公钥基础架构,是一组由硬件、软件、参与者、管理政策与流程组成的基础架构,其目的在于创造、管理、分配、使用、存储以及撤销数字证书。(节选维基百科)
PKI是借助CA(权威数字证书颁发/认证机构)将用户的个人身份跟公开密钥链接在一起,它能够确保每个用户身份的唯一性,这种链接关系是通过注册和发布过程实现,并且根据担保级别,链接关系可能由CA和各种软件或在人为监督下完成。PKI用来确定链接关系的这一角色称为RA(Registration Authority, 注册管理中心),RA能够确保公开密钥和个人身份链接,可以防抵赖,防篡改。在微软的公钥基础建设下,RA又被称为CA,目前大多数称为CA。
PKI组成要素
从上面可以得知PKI的几个主要组成要素,用户(使用PKI的人或机构),认证机构(CA,颁发证书的人或机构),仓库(保存证书的数据库)等。
非对称加密
本文提到的密钥均为非对称加密,有公钥和私钥之分,并且他们总是成对出现,它们的特点就是其中一个加密的数据,只能使用另一个解密,即使它本身也无法解密,也就是说公钥加密的,私钥可以解密,私钥加密的,公钥可以解密。
证书签名请求CSR
它是向CA机构申请数字证书时使用的请求文件,这里的CSR不是证书,而向权威证书颁发机构获得签名证书的申请,当CA机构颁发的证书过期时,你可以使用相同的CSR来申请新的证书,此时key不变。
数字签名
数字签名就是“非对称加密+摘要算法”,其目的不是为了加密,而是为了防抵赖或者他们篡改数据。其核心思想是:比如A要给B发送数据,A先用摘要算法得到数据的指纹,然后用A的私钥加密指纹,加密后的指纹就是A的签名,B收到数据和A的签名后,也用同样的摘要算法计算指纹,然后用A公开的公钥解密签名,比较两个指纹,如果相同,说明数据没有被篡改,确实是A发过来的数据。假设C想改A发给B的数据来欺骗B,因为篡改数据后指纹会变,要想跟A的签名里面的指纹一致,就得改签名,但由于没有A的私钥,所以改不了,如果C用自己的私钥生成一个新的签名,B收到数据后用A的公钥根本就解不开。(来源于网络)
数字证书格式
数字证书格式有很多,比如.pem,.cer或者.crt等。
PKI工作流程
下图来源于网络,上半部分最右边就是CA机构,可以颁发证书。证书订阅人,首先去申请一个证书,为了申请这个证书,需要去登记,告诉它,我是谁,我属于哪个组织,到了登记机构,再通过CSR,发送给CA中心,CA中心通过验证通过之后 ,会颁发一对公钥和私钥,并且公钥会在CA中心存一份;证书订阅人拿到证书以后,部署在服务器;
当用户访问我们的web服务器时,它会请求我们的证书,服务器会把公钥发送给我们的客户端,客户端会去验证我们证书的合法性,客户端是如何验证证书是否有效呢?CA中心会把过期证书放在CRL服务器上面 ,这个CRL服务会把所有过期的证书形成一条链条,所以他的性能非常的差,所以又推出了OCSP程序,OCSP可以就一个证书进行查询,它是否过期,浏览器可以直接去查询OCSP响应程序,但OCSP响应程序效率还不是很高,最终往往我们会把web服务器如nginx有一个ocsp开关,当我们打开这个开关以后,会有nginx服务器主动的去ocsp服务器去查询,这样大量的客户端直接从web服务器就可以直接获取到证书是否有效。
CFSSL介绍
CFSSL是什么?
cfssl是使用go编写,由CloudFlare开源的一款PKI/TLS工具。主要程序有cfssl,是CFSSL的命令行工具,cfssljson用来从cfssl程序获取JSON输出,并将证书,密钥,CSR和bundle写入文件中。
安装CFSSL 安装 cfssl 工具集 1 2 3 4 5 6 7 8 9 10 11 12 sudo mkdir -p /opt/ k8s/{work,bin,cert} && cd / opt/k8s/ work wget https://gi thub.com/cloudflare/ cfssl/releases/ download/v1.4.1/ cfssl_1.4.1 _linux_amd64 mv cfssl_1.4.1 _linux_amd64 /opt/ k8s/bin/ cfssl wget https://gi thub.com/cloudflare/ cfssl/releases/ download/v1.4.1/ cfssljson_1.4.1 _linux_amd64 mv cfssljson_1.4.1 _linux_amd64 /opt/ k8s/bin/ cfssljson wget https://gi thub.com/cloudflare/ cfssl/releases/ download/v1.4.1/ cfssl-certinfo_1.4.1 _linux_amd64 mv cfssl-certinfo_1.4.1 _linux_amd64 /opt/ k8s/bin/ cfssl-certinfo chmod +x /opt/ k8s/bin/ * export PATH=/opt/ k8s/bin:$PATH
生成证书 注意 本文所有操作均在master1节点执行 创建配置文件 CA 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cat > ca-config .json << EOF { "signing" : { "default" : { "expiry" : "87600h" }, "profiles" : { "kubernetes" : { "usages" : ["signing" , "keyencipherment" , "serverauth" , "clientauth" ], "expiry" : "876000h" } } } } EOF
signing :表示该证书可用于签名其它证书(生成的 ca.pem 证书中CA=TRUE );
server auth :表示 client 可以用该该证书对 server 提供的证书进行验证;
client auth :表示 server 可以用该该证书对 client 提供的证书进行验证;
“expiry”: “876000h” :证书有效期设置为 100 年;
创建证书签名请求文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cd /opt /k8s/workcat > ca -csr.json << EOF { "CN" : "kubernetes-ca" , "key" : { "algo" : "rsa" , "size" : 2048 }, "names" : [{ "C" : "CN" , "ST" : "BeiJing" , "L" : "BeiJing" , "O" : "k8s" , "OU" : "opsnull" }], "ca" : { "expiry" : "876000h" } } EOF
CN:Common Name :kube-apiserver 从证书中提取该字段作为请求的用户名(User Name),浏览器使用该字段验证网站是否合法;
O:Organization :kube-apiserver 从证书中提取该字段作为请求用户所属的组(Group);
kube-apiserver 将提取的 User、Group 作为 RBAC 授权的用户标识;
注意:
不同证书 csr 文件的 CN、C、ST、L、O、OU 组合必须不同,否则可能出现PEER’S CERTIFICATE HAS AN INVALID SIGNATURE 错误;
后续创建证书的 csr 文件时,CN 都不相同(C、ST、L、O、OU 相同),以达到区分的目的;
生成 CA 证书和私钥 1 2 3 cd /opt /k8s/workcfssl gencert -initca ca -csr.json | cfssljson -bare ca ls ca *
分发证书文件 1 2 3 4 5 6 7 8 9 cd /opt/k8s/worksource /opt/k8s/bin/environment.shNODE_IPS=("192.168.220.101" "192.168.220.102" "192.168.220.103" "192.168.220.104" "192.168.220.105" ) for node_ip in ${NODE_IPS[@]} do echo ">>> ${node_ip} " ssh root@${node_ip} "mkdir -p /etc/kubernetes/cert" scp ca*.pem ca-config.json root@${node_ip} :/etc/kubernetes/cert done
安装和配置 kubectl 本文档只需要部署一次,生成的 kubeconfig 文件是通用的,可以拷贝到需要执行kubectl 命令的机器的 ~/.kube/config 位置;
下载和分发 kubectl 二进制文件 1 2 https:// dl.k8s.io/v1.17.3/ kubernetes-server-linux-amd64.tar.gz
分发到所有使用 kubectl 工具的节点:(master) 将命令分发到master节点/opt/k8s/bin 下,并添加PATH export PATH=/opt/k8s/bin:$PATH
创建 admin 证书和私钥 kubectl 使用 https 协议与 kube-apiserver 进行安全通信,kube-apiserver 对 kubectl 请求包含的证书进行认证和授权。 kubectl 后续用于集群管理,所以这里创建具有最高权限的 admin 证书。
创建证书签名请求: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cd /opt /k8s/certcat > admin-csr.json << EOF { "CN" :"admin" , "hosts" :[], "key" :{ "algo" :"rsa" , "size" :2048 }, "names" :[ { "C" :"CN" , "ST" :"BeiJing" , "L" :"BeiJing" , "O" :"system:masters" , "OU" :"opsnull" } ] } EOF
O: system:masters :kube-apiserver 收到使用该证书的客户端请求后,为请求添加组(Group)认证标识 system:masters ;
预定义的 ClusterRoleBinding cluster-admin 将 Group system:masters 与Role cluster-admin 绑定,该 Role 授予操作集群所需的最高权限;
该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;
生成证书和私钥: 1 2 3 4 5 6 cd /opt/ k8s/cert cfssl gencert -ca=/opt/ k8s/cert/ ca.pem \ -ca-key=/opt/ k8s/cert/ ca-key.pem \ -config=/opt/ k8s/cert/ ca-config.json \ -profile=kubernetes admin-csr.json | cfssljson -bare admin ls admin*
忽略警告消息 [WARNING] This certificate lacks a “hosts” field. ;
创建 kubeconfig 文件 kubectl 使用 kubeconfig 文件访问 apiserver,该文件包含 kube-apiserver 的地址和认证信息(CA 证书和客户端证书):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cd /opt /k8s /work source /opt /k8s /bin /environment .sh kubectl config set-cluster kubernetes \--certificate-authority=/opt/k8s/cert/ca.pem \--embed-certs=true \--server=192.168.220.101:6443 \--kubeconfig=kubectl.kubeconfig kubectl config set-credentials admin \--client-certificate=/opt/k8s/certcert/admin.pem \--client-key=/opt/k8s/cert/admin-key.pem \--embed-certs=true \--kubeconfig=kubectl.kubeconfig kubectl config set-context kubernetes \--cluster=kubernetes \--user=admin \--kubeconfig=kubectl.kubeconfig kubectl config use-context kubernetes --kubeconfig=kubectl.kubeconfig
–certificate-authority :验证 kube-apiserver 证书的根证书;
–client-certificate 、 –client-key :刚生成的 admin 证书和私钥,与kube-apiserver https 通信时使用;
–embed-certs=true :将 ca.pem 和 admin.pem 证书内容嵌入到生成的kubectl.kubeconfig 文件中(否则,写入的是证书文件路径,后续拷贝 kubeconfig 到其它机器时,还需要单独拷贝证书文件,不方便。);
–server :指定 kube-apiserver 的地址,这里指向第一个节点上的服务;
分发 kubeconfig 文件 1 2 mkdir -p ~/.kubecp kubectl.kubeconfig ~/.kube/config
部署 etcd 集群 etcd 是基于 Raft 的分布式 KV 存储系统,由 CoreOS 开发,常用于服务发现、共享配置以及并发控制(如 leader 选举、分布式锁等)。
kubernetes 使用 etcd 集群持久化存储所有 API 对象、运行数据。
本文档介绍部署一个三节点高可用 etcd 集群的步骤:
下载和分发 etcd 二进制文件;
创建 etcd 集群各节点的 x509 证书,用于加密客户端(如 etcdctl) 与 etcd 集群、etcd 集群之间的通信;
创建 etcd 的 systemd unit 文件,配置服务参数;
检查集群工作状态;
etcd 集群节点名称和 IP 如下:
1 2 3 k8s -01 :192.168.220.100 k8s -02 :192.168.220.101 k8s -03 :192.168.220.102
注意:
如果没有特殊指明,本文档的所有操作均在k8s-01 节点上执行;
flanneld 与本文档安装的 etcd v3.4.x 不兼容,如果要安装 flanneld(本文档使用calio),则需要将 etcd 降级到 v3.3.x 版本;
下载和分发 etcd 二进制文件 到 etcd 的 release 页面 下载最新版本的发布包: 1 2 3 cd /opt/k8s/work wget https://github.com/coreos/etcd/releases/download/v3.4.3/etcd-v3.4.3-linux-amd64.tar.gz tar -xvf etcd-v3.4.3-linux-amd64.tar.gz
分发二进制文件到集群所有节点: 1 2 3 4 5 6 7 8 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in ${NODE_IPS[@]} do echo ">>> ${node_ip}" scp etcd-v3.4.3-linux-amd64/etcd* root@${node_ip}:/opt/k8s/bin ssh root@${node_ip} "chmod +x /opt/k8s/bin/*" done
创建 etcd 证书和私钥 创建证书签名请求: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cd /opt/k8s/work cat > etcd-csr.json << EOF { "CN" : "etcd" , "hosts" : [ "127.0.0.1" , "192.168.220.103" , "192.168.220.104" , "192.168.220.105" ] , "key" : { "algo" : "rsa" , "size" : 2048 } , "names" : [ { "C" : "CN" , "ST" : "BeiJing" , "L" : "BeiJing" , "O" : "k8s" , "OU" : "opsnull" } ] } EOF
hosts :指定授权使用该证书的 etcd 节点 IP 列表,需要将 etcd 集群所有节点 IP都列在其中;
生成证书和私钥: 1 2 3 4 5 6 cd /opt/k8s/work cfssl gencert -ca=/opt/k8s/cert/ca.pem \ -ca-key=/opt/k8s/cert/ca-key.pem \ -config=/opt/k8s/cert/ca-config.json \ -profile=kubernetes etcd-csr.json | cfssljson -bare etcd ls etcd*pem
分发生成的证书和私钥到各 etcd 节点: 1 2 3 4 5 6 7 8 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in ${NODE_IPS[@]} do echo ">>> ${node_ip}" ssh root@${node_ip} "mkdir -p /etc/etcd/cert" scp etcd*.pem root@${node_ip}:/etc/etcd/cert/ done
创建 etcd 的 systemd unit 模板文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 cd /opt/k8s/worksource /opt/k8s/bin/environment.shcat > etcd.service.template <<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=${ETCD_DATA_DIR} ExecStart=/opt/k8s/bin/etcd \\ --data-dir=${ETCD_DATA_DIR} \\ --wal-dir=${ETCD_WAL_DIR} \\ --name=##NODE_NAME## \\ --cert-file=/etc/etcd/cert/etcd.pem \\ --key-file=/etc/etcd/cert/etcd-key.pem \\ --trusted-ca-file=/etc/kubernetes/cert/ca.pem \\ --peer-cert-file=/etc/etcd/cert/etcd.pem \\ --peer-key-file=/etc/etcd/cert/etcd-key.pem \\ --peer-trusted-ca-file=/etc/kubernetes/cert/ca.pem \\ --peer-client-cert-auth \\ --client-cert-auth \\ --listen-peer-urls=https://##NODE_IP##:2380 \\ --initial-advertise-peer-urls=https://##NODE_IP##:2380 \\ --listen-client-urls=https://##NODE_IP##:2379,http://127.0.0.1:2379 \\ --advertise-client-urls=https://##NODE_IP##:2379 \\ --initial-cluster-token=etcd-cluster-0 \\ --initial-cluster=${ETCD_NODES} \\ --initial-cluster-state=new \\ --auto-compaction-mode=periodic \\ --auto-compaction-retention=1 \\ --max-request-bytes=33554432 \\ --quota-backend-bytes=6442450944 \\ --heartbeat-interval=250 \\ --election-timeout=2000 Restart=on-failure RestartSec=5 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
WorkingDirectory 、 –data-dir :指定工作目录和数据目录为${ETCD_DATA_DIR} ,需在启动服务前创建这个目录;
–wal-dir :指定 wal 目录,为了提高性能,一般使用 SSD 或者和 –data-dir 不同的磁盘;
–name :指定节点名称,当 –initial-cluster-state 值为 new 时, –name 的参数值必须位于 –initial-cluster 列表中;
–cert-file 、 –key-file :etcd server 与 client 通信时使用的证书和私钥;
–trusted-ca-file :签名 client 证书的 CA 证书,用于验证 client 证书;
–peer-cert-file 、 –peer-key-file :etcd 与 peer 通信使用的证书和私钥;
–peer-trusted-ca-file :签名 peer 证书的 CA 证书,用于验证 peer 证书;
为各节点创建和分发 etcd systemd unit 文件 替换模板文件中的变量,为各节点创建 systemd unit 文件:
1 2 3 4 5 6 7 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for (( i=0; i < 3; i++ )) do sed -e "s/##NODE_NAME##/${ETCD_NAMES[i]}/" -e "s/##NODE_IP##/${ETCD_IPS[i]}/" etcd.service.template > etcd-${NODE_IPS[i]}.service done ls *.service
NODE_NAMES 和 NODE_IPS 为相同长度的 bash 数组,分别为节点名称和对应的 IP;
分发生成的 systemd unit 文件:
1 2 3 4 5 6 7 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in ${NODE_IPS[@]} do echo ">>> ${node_ip}" scp etcd-${node_ip}.service root@${node_ip}:/etc/systemd/system/etcd.service done
启动 etcd 服务 1 2 3 4 5 6 7 8 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in ${NODE_IPS[@]} do echo ">>> ${node_ip}" ssh root@${node_ip} "mkdir -p ${ETCD_DATA_DIR} ${ETCD_WAL_DIR}" ssh root@${node_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd &" done
必须先创建 etcd 数据目录和工作目录;
etcd 进程首次启动时会等待其它节点的 etcd 加入集群,命令 systemctl startetcd 会卡住一段时间,为正常现象;
检查启动结果 1 2 3 4 5 6 7 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in ${NODE_IPS[@]} do echo ">>> ${node_ip}" ssh root@${node_ip} "systemctl status etcd|grep Active" done
确保状态为 active (running) ,否则查看日志,确认原因:
验证服务状态 部署完 etcd 集群后,在任一 etcd 节点上执行如下命令:
1 2 3 4 5 6 7 8 9 10 11 cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in ${ETCD_IPS[@]} do echo ">>> ${node_ip}" /opt/k8s/bin/etcdctl \ --endpoints=https://${node_ip}:2379 \ --cacert=/etc/kubernetes/cert/ca.pem \ --cert=/etc/etcd/cert/etcd.pem \ --key=/etc/etcd/cert/etcd-key.pem endpoint health done
3.4.3 版本的 etcd/etcdctl 默认启用了 V3 API,所以执行 etcdctl 命令时不需要再指定环境变量 ETCDCTL_API=3 ;
从 K8S 1.13 开始,不再支持 v2 版本的 etcd;
预期输出:
输出均为 healthy 时表示集群服务正常。
查看当前的 leader 1 2 3 4 5 6 source /opt/k8s/bin/environment.sh /opt/k8s/bin/etcdctl \ -w table --cacert=/etc/kubernetes/cert/ca.pem \ --cert=/etc/etcd/cert/etcd.pem \ --key=/etc/etcd/cert/etcd-key.pem \ --endpoints=${ETCD_ENDPOINTS} endpoint status
输出:
可见,当前的 leader 为192.168.220.100。