九零不老心
发布于 2019-11-14 / 7 阅读 / 0 评论 / 0 点赞

kubernetes v1.14.2安装详解

链接: https://pan.baidu.com/s/1g54U6lls-5LgcxkVRjBBXA 提取码: nafb 序言: 下面是使用kubeadm自动化安装三master控制节点,多node(worker)工作节点教程 kubernetes中涉及证书内容,如果你想直接签发10年证书,可以先阅读下末尾内容,再从开头进行阅读 本教程使用的etcd是通过kubeadm自动部署k8s pod到三个master上的,如果想使用外部etcd集群,可以先阅读下末尾内容,再从开头进行阅读 另外不论是docker版本、k8s各组件版本、以及第三方应用版本,都应该是互相匹配且支持的,否则无法组合,共同工作 另外各版本的命令、参数因版本的不同,会有不同差异,使用时请-help或者查阅官方详细文档 建议整体阅读,有大致理解了解以后,再进行试验 如果完全重新安装,建议完全清理以前生成的文件,以及重启相关的服务,最好重启服务器,生产环境中,记得要定期备份etcd数据等 一、基础环境 #环境 kubernetes v1.14.2(注意kubelet client跟server最好版本一致) kubeadm 默认证书有效期为1年 linux CentOS 64 Linux release 7.5.1804 (Core) 192.168.10.241 master01 192.168.10.242 master02 192.168.10.243 master03 192.168.10.244 node01 192.168.10.245 node02 192.168.10.246 node03 #所有节点设置各自的hostname(hostname最好不要包含特殊字符比如下滑线,kubeadm会对此有校验) hostnamectl set-hostname master01 hostnamectl set-hostname master02 hostnamectl set-hostname master03 hostnamectl set-hostname node01 hostnamectl set-hostname node02 hostnamectl set-hostname node03 #所有节点加入/etc/hosts解析 cat <<EOF >> /etc/hosts 192.168.10.241 master01 192.168.10.242 master02 192.168.10.243 master03 192.168.10.244 node01 192.168.10.245 node02 192.168.10.246 node03 EOF #所有节点永久关闭防火墙(非常不建议内网k8s集群之间架设有防火墙“端口贼多”,k8s对外服务上架设防火墙就好) systemctl stop firewalld systemctl disable firewalld #所有节点永久关闭selinux sed -i 's/^SELINUX=.*$/SELINUX=disabled/' /etc/selinux/config reboot #查看当前状态getenforce #所有节点关闭swap,并设置其他一些内核参数,内核参数范例并不完整,请切合实际修改 cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.swappiness=0 EOF sysctl --system #生效所有配置,查看所有参数sysctl -a swapoff -a #临时关闭配置文件“/etc/fstab”中所有的交换空间 sed -i 's/^\/dev\/mapper\/centos-swap/#&/' /etc/fstab #永久关闭swap #所有节点所有节点安装docker,具体安装过程请详见官方教程:https://docs.docker.com/install/linux/docker-ce/centos/,还需要参考k8s官网https://kubernetes.io/docs/setup/cri/#docker echo "nameserver 114.114.114.114" >> /etc/resolv.conf yum install -y yum-utils  device-mapper-persistent-data  lvm2 && yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io cat > /etc/docker/daemon.json <<EOF { "registry-mirrors": ["http://f1361db2.m.daocloud.io"], "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" }, "exec-opts": ["native.cgroupdriver=systemd"], "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF # systemctl restart docker systemctl enable docker && systemctl restart docker #所有节点iptables开启forward iptables -P FORWARD ACCEPT #所有节点开启ipvs内核模块 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 #校验ipvs相关模块是否启用 lsmod | grep -e ip_vs -e nf_conntrack_ipv4 二、所有节点安装kubeadm、kubelet和kubectl、ipvsadm #所有节点配置阿里云repo镜像源 cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF #所有节点安装kubeadm、kubelet和kubectl、ipvsadm yum list kubeadm --showduplicates | sort -r yum install -y kubelet-1.14.1 kubeadm-1.14.1 kubectl-1.14.1 ipvsadm systemctl enable kubelet && systemctl start kubelet #配置kubelet参数 cat <<EOF > /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS="--runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice" EOF 三、所有master节点配置HAproxy代理和keepalived #所有master节点,安装haproxy docker镜像 docker pull haproxy:latest #创建haproxy的配置文件 mkdir -pv /etc/haproxy cat <<EOF > /etc/haproxy/haproxy.cfg global log 127.0.0.1 local0 err maxconn 50000 uid 99 #nobody gid 99 #nobody #daemon nbproc 1 pidfile haproxy.pid defaults mode http log 127.0.0.1 local0 err maxconn 50000 retries 3 timeout connect 5s timeout client 30s timeout server 30s timeout check 2s listen admin_stats mode http bind 0.0.0.0:1080 log 127.0.0.1 local0 err stats refresh 30s stats uri     /haproxy-status stats realm   Haproxy\ Statistics stats auth    admin:admin stats hide-version stats admin if TRUE frontend k8smaster-haproxy-https bind 0.0.0.0:8443 mode tcp default_backend k8smaster-https backend k8smaster-https mode tcp balance roundrobin server master01 192.168.10.241:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3 server master02 192.168.10.242:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3 server master03 192.168.10.243:6443 weight 1 maxconn 1000 check inter 2000 rise 2 fall 3 EOF #检测配置文件错误 docker run -it --rm --name haproxy-syntax-check my-haproxy haproxy -c -f /etc/haproxy/haproxy.cfg #启动haproxy docker run  -d --name k8smaster-haproxy -v /etc/haproxy:/usr/local/etc/haproxy:ro -p 8443:8443 -p 1080:1080 --restart always  haproxy:latest #重载haproxy配置 docker kill -s HUP k8smaster-haproxy #查看haproxy日志 docker logs k8smaster-haproxy #浏览器查看状态 http://192.168.10.241:1080/haproxy-status http://192.168.10.242:1080/haproxy-status http://192.168.10.243:1080/haproxy-status #所有master节点,安装keepalived docker镜像 docker pull osixia/keepalived:latest #所有master节点,启动keepalived docker docker run -d --name k8smaster-keepalived --net=host --cap-add=NET_ADMIN -e KEEPALIVED_INTERFACE=ens33 -e KEEPALIVED_VIRTUAL_IPS="#PYTHON2BASH:['192.168.10.240']" -e KEEPALIVED_UNICAST_PEERS="#PYTHON2BASH:['192.168.10.241','192.168.10.242','192.168.10.243']" -e KEEPALIVED_PASSWORD=admin --restart always osixia/keepalived:latest #查看keepalived docker日志 docker logs k8smaster-keepalived #此时vip 192.168.10.240应该会绑定到三台的master01上 ping 192.168.10.240 #可通 #如果失败,删除命令为 docker rm -f k8smaster-keepalived ip a del 192.168.10.240/32 dev ens33 四、配置第一个master(参数使用说明,请参考官网https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-config/#cmd-config-from-file) #查看默认组件image list kubeadm config images list #查看默认配置(kubeadm config print init-defaults or kubeadm config print join-defaults),并初始化文件(详细参数配置参考https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1) cd /root/ kubeadm config print init-defaults > k8s-init-master01.yaml #修改k8s-init-master01.yaml配置文件 详见同级目录的k8s-init-master01.yaml文件 #提前拉取镜像 kubeadm config images pull --config k8s-init-master01.yaml #查看vip240是否在master01上(如果不在,可以同时重启另两个master的docker keepalived服务,将vip漂移到master01上) ip addr docker restart k8smaster-keepalived #初始化(如果初始化超时并失败,很可能一个原因是240的vip没有在master01上,kubelet报错连接vip失败,ip addr 可以查看ip信息) kubeadm init --config k8s-init-master01.yaml mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config #systemctl status -l kubelet 会报Unable to update cni config: No networks found in /etc/cni/net.d 因为还没安装k8s的flannel cni插件 #注意保存返回的join命令 kubeadm join 192.168.10.240:8443 --token rx75vh.v77joay2977m2p5g \ --discovery-token-ca-cert-hash sha256:fc9c5027264df3320d30894078f75daf69565ac50dbb411e956493e65646e4f3 \ --experimental-control-plane kubeadm join 192.168.10.240:8443 --token rx75vh.v77joay2977m2p5g \ --discovery-token-ca-cert-hash sha256:fc9c5027264df3320d30894078f75daf69565ac50dbb411e956493e65646e4f3 #重置节点命令是(如果全部集群重置,每个master及node节点都需要操作): kubeadm reset -f iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X ipvsadm --clear rm -rf $HOME/.kube systemctl daemon-reload && systemctl restart kubelet #copy证书到其他master节点,不用传输证书到node节点 cd /etc/kubernetes && tar -czvf k8s-ca.tar.gz admin.conf pki/ca.* pki/sa.* pki/front-proxy-ca.* pki/etcd/ca.* && cd ~ #scp到master02、master03,然后解压相同级别目录tar -xzvf k8s-ca.tar.gz scp /etc/kubernetes/k8s-ca.tar.gz master02:/etc/kubernetes/ scp /etc/kubernetes/k8s-ca.tar.gz master03:/etc/kubernetes/ #解压master02、master03下的k8s-ca.tar.gz cd /etc/kubernetes/ && tar -xzvf k8s-ca.tar.gz && cd ~ cd /etc/kubernetes/ && tar -xzvf k8s-ca.tar.gz && cd ~ 五、配置第二个master(以下是使用init phase分阶段加入集群教程) #copy k8s-init-master01.yaml为k8s-init-master02.yaml,并修改内容 具体请查看同级目录的k8s-init-master02.yaml #初始化 #配置证书 kubeadm init phase certs all --config k8s-init-master02.yaml kubeadm init phase etcd local --config k8s-init-master02.yaml #初始化kubelet kubeadm init phase kubeconfig kubelet --config k8s-init-master02.yaml kubeadm init phase kubelet-start --config k8s-init-master02.yaml mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config #将etcd加入集群 kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member add master02 https://192.168.10.242:2380 #查看etcd集群已有节点 kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member list #启动kube-apiserver、kube-controller-manager、kube-scheduler kubeadm init phase kubeconfig all --config k8s-init-master02.yaml kubeadm init phase control-plane all --config k8s-init-master02.yaml #标记节点为master #获取状态 kubectl get nodes #ROLES为none状态 #标记为master kubeadm init phase mark-control-plane --config k8s-init-master02.yaml #ROLES为master状态 #获取状态 kubectl get nodes #ROLES为master状态 六、配置第三个master(以下是使用init phase分阶段加入集群教程) #copy k8s-init-master02.yaml为k8s-init-master03.yaml,并修改内容 具体请查看同级目录的k8s-init-master03.yaml #初始化 #配置证书 kubeadm init phase certs all --config k8s-init-master03.yaml kubeadm init phase etcd local --config k8s-init-master03.yaml #初始化kubelet kubeadm init phase kubeconfig kubelet --config k8s-init-master03.yaml kubeadm init phase kubelet-start --config k8s-init-master03.yaml mkdir -p $HOME/.kube && cp -i /etc/kubernetes/admin.conf $HOME/.kube/config &&  chown $(id -u):$(id -g) $HOME/.kube/config #将etcd加入集群 kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member add master03 https://192.168.10.243:2380 #查看etcd集群已有节点 kubectl exec -n kube-system etcd-master01 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.241:2379 member list #启动kube-apiserver、kube-controller-manager、kube-scheduler kubeadm init phase kubeconfig all --config k8s-init-master03.yaml kubeadm init phase control-plane all --config k8s-init-master03.yaml #标记节点为master #获取状态 kubectl get nodes #ROLES为none状态 #标记为master kubeadm init phase mark-control-plane --config k8s-init-master03.yaml #ROLES为master状态 #获取状态 kubectl get nodes #ROLES为master状态 七、安装flannel(在任意一个master节点执行) #下载flannel的yml文件 wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml #查看net-conf.json的network跟你的环境网络是否同一个网段,如果不是请修改kube-falnnel.yml内容为实际网段内容 net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } } #flannel默认会使用主机的第一张网卡,如果你有多张网卡,需要增加参数,单独指定特定网卡名称 containers: - name: kube-flannel image: quay.io/coreos/flannel:v0.11.0-amd64 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr - --iface=ens33 #执行安装flannel kubectl apply -f kube-flannel.yml #查看节点状态 kubectl get nodes #status都为Ready kubectl get pods --all-namespaces #有很多pod systemctl status -l kubelet #不再报cni的错误 八、在所有node节点操作 #在所有node节点上运行,master01上初始化后返回的不带有参数--experimental-control-plane的join语句 执行上面master01返回的join语句 #如果忘记加入命令,可以查询(master端查询) kubeadm token create --print-join-command #重置命令 kubeadm reset -f iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X ipvsadm --clear rm -rf $HOME/.kube systemctl daemon-reload && systemctl restart kubelet 九、校验是否成功(任意一个master节点执行) #节点状态 kubectl get nodes #组件状态 kubectl get cs #查看所有pods kubectl get pods --namespace kube-system -o wide #查看pod日志 kubectl logs etcd-master02 --namespace kube-system #查看所有服务 kubectl get svc --all-namespaces #查看指定服务 kubectl get svc --namespace kube-system #服务账户 kubectl get serviceaccount --all-namespaces #查看角色 kubectl get roles --all-namespaces #集群信息 kubectl cluster-info #验证dns功能 kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools nslookup kubernetes.default #检查是否创建了deployments任务: kubectl get deployments --all-namespaces #编辑deployments配置 kubectl edit deployments -n kube-system 检查是否创建了副本控制器ReplicationController: kubectl get rc --all-namespaces #检查死否创建了副本集replicasets: kubectl get rs --all-namespaces 十、部署高可用 CoreDNS(任意一个master节点执行,如果已是高可用,不需要执行本步骤,官方参考文档https://github.com/coredns/deployment/tree/master/kubernetes) #查看pod kubectl get pods --all-namespaces -o wide #发现初始安装的coredns pod都在单点master03上,那如果master03宕机,coredns的服务就挂了 #下载并生成coredns.yaml文件 wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/coredns.yaml.sed wget https://raw.githubusercontent.com/coredns/deployment/master/kubernetes/deploy.sh yum install -y epel-release && yum install -y jq && chmod u+x deploy.sh ./deploy.sh > coredns.yaml #先删除coredns kubectl delete -f coredns.yaml kubectl get pods --all-namespaces -o wide #coredns.yaml为同级目录下的coredns.yaml #安装coredns kubectl apply  -f coredns.yaml kubectl get pods --all-namespaces -o wide #验证dns功能 kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools nslookup kubernetes.default 十一、安装kubernetes dashboard(任意一个master节点执行,官方参考文档https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#deploying-the-dashboard-ui , https://github.com/kubernetes/dashboard/wiki/Creating-sample-user) #下载kubernetes-dashboard.yaml wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml #修改kubernetes-dashboard.yaml为同级目录下的kubernetes-dashboard.yaml内容 #安装kubernetes-dashboard kubectl apply  -f kubernetes-dashboard.yaml #新建dashboard-adminuser.yaml文件,内容同同级目录下的dashboard-adminuser.yaml内容 #新建dashborad管理权限用户(请注意根据自己实际需求设定) kubectl apply  -f dashboard-adminuser.yaml #给浏览器生成客户端证书 grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d > kubecfg.crt grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d > kubecfg.key openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client" #此时,可以设置导出密码,kubecfg.p12就是生成的个人证书 #浏览器导入证书kubecfg.p12 需要人工手动操作浏览器设置导入证书,如果生成的时候设置了导出密码,还需要在导入的时候输入相同密码 #导入成功后,重启浏览器,然后浏览器访问Dashboard UI https://192.168.10.240:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ #使用token登录界面,界面输入获取的token(已经登录成功,不过这一步因为浏览器版本、品牌(谷歌火狐目前测试正常)、https证书等的原因,各种报错结果,但以上步骤确定是正确的) #获取kuberntes-dashboard用户token kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kubernetes-dashboard | awk '{print $1}') | grep token: | awk '{print $2}' #获取service account admin-user的Token kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') | grep token: | awk '{print $2}' eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXM4cWhkIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIxYzU3MzVjMy03MmRjLTExZTktYmE3ZC0wMDBjMjk4Y2M4YjMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.DkEKxwIaSeaEWRW10RefhBGoFneF4S_A_WDhqAN1bhZDuMQY93cqm7-WIw5iMvqt6SWGZSyb8KsaGUNR5ISmg5SAuLc6TUezzCyGJuntoTQRLYN0NIipbCEPj7OWGTVjiChr0Ss4X4opDpBUvQ7OkL-UzSQLpYOtSGYFPKa9CXUF5vjnNa4ova5KO61HJLInMZ-4XkPyWubsoyqihPVHXu36TnWJ0pEmpLxt9NhdCykUy1Oxcojj0r889cl5hUiLCl2Wk3mlMs3azC1pCOvRY0mcLmzz8g4OihVYMc5FK0rqG6LQ4K9SHpwB0AZQnhgzC5feHMGL9o5A2W-qek2uWQ #使用kubeconfig文件登录(User in kubeconfig file need either username & password or token,这里我们使用token,参考链接https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) DASHBOARD_TOCKEN=$(kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') | grep token: | awk '{print $2}') kubectl config set-cluster kubernetes --server=https://192.168.10.240:8443 --kubeconfig=/root/dashboard-admin.conf kubectl config set-credentials dashboard-admin --token=$DASHBOARD_TOCKEN --kubeconfig=/root/dashboard-admin.conf kubectl config set-context dashboard-admin@kubernetes --cluster=kubernetes --user=dashboard-admin --kubeconfig=/root/dashboard-admin.conf kubectl config use-context dashboard-admin@kubernetes --kubeconfig=/root/dashboard-admin.conf 生成的dashboard-admin.conf即可用于kubeconfig方式登录dashboard #注意,以上是api方式访问kubernetes dashboard,当然也可以create nginx ingress for dashboard,但不如api方式更直接,毕竟ingress挂了,也就没法ingress方式访问dashboard了 十二、模拟master01故障 #master01上执行 shutdown -h now #需要过一段时间,k8s才会检测到master01 not ready #浏览器重新打开https://192.168.10.240:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ 看是否正常 #dashborad节点菜单项上master01已就绪状态变成Unknown #其他正常master执行kubectl get nodes看结果 #master01的status状态变为NotReady #查看pod是否正常 kubectl get pods --namespace kube-system -o wide #其他服务都正常,表明kubernetesHA高可用模式成功 #当然现在重新启动master01(没有破坏过master01的数据,只是做了重启),重启服务器完毕后,整个集群的状态又会自动恢复正常。 #为了模拟更真实的故障恢复,我们破坏master01的数据更彻底些 kubeadm reset -f #再次查询集群状态等 kubectl get nodes #master01的status状态变为NotReady kubectl get pods --namespace kube-system -o wide 十三、模拟master01故障以后的恢复 #首先在一台正常master上运行下面的命令获取etcd集群中故障member的ID(正常master节点执行) ETCD=`docker ps|grep etcd|grep -v POD|awk '{print $1}'` docker exec -it ${ETCD}   etcdctl   --endpoints https://127.0.0.1:2379   --ca-file /etc/kubernetes/pki/etcd/ca.crt   --cert-file /etc/kubernetes/pki/etcd/peer.crt   --key-file /etc/kubernetes/pki/etcd/peer.key   cluster-health #移除故障节点的etcd(正常master节点执行) ETCD=`docker ps|grep etcd|grep -v POD|awk '{print $1}'` docker exec -it ${ETCD}   etcdctl   --endpoints https://127.0.0.1:2379   --ca-file /etc/kubernetes/pki/etcd/ca.crt   --cert-file /etc/kubernetes/pki/etcd/peer.crt   --key-file /etc/kubernetes/pki/etcd/peer.key member remove 6bb5472fc24f7d4c docker exec -it ${ETCD}   etcdctl   --endpoints https://127.0.0.1:2379   --ca-file /etc/kubernetes/pki/etcd/ca.crt   --cert-file /etc/kubernetes/pki/etcd/peer.crt   --key-file /etc/kubernetes/pki/etcd/peer.key   cluster-health #重新加入正常的机器(要与原来master01主机名、IP一致),并且复用ca证书、k8s-init-master01.yaml #注意修改initial-cluster: "master01=https://192.168.10.241:2380" 为 initial-cluster: "master01=https://192.168.10.241:2380,master02=https:/192.168.10..242:2380,master03=https:192.168.10.10.243:2380" initial-cluster-state: existing #重置master01(之后都在master01上执行) #kubeadm reset -f iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X ipvsadm --clear rm -rf $HOME/.kube systemctl daemon-reload && systemctl restart kubelet #重新做一遍master01初始化 #记得重新copy正常master上的ca证书等 cd /etc/kubernetes/ && tar -xzvf k8s-ca.tar.gz && cd ~ #配置证书 kubeadm init phase certs all --config k8s-init-master01.yaml kubeadm init phase etcd local --config k8s-init-master01.yaml #初始化kubelet kubeadm init phase kubeconfig kubelet --config k8s-init-master01.yaml kubeadm init phase kubelet-start --config k8s-init-master01.yaml mkdir -p $HOME/.kube && sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config #将etcd加入集群 #查看etcd集群已有节点 kubectl exec -n kube-system etcd-master02 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.242:2379 member list #加入集群 kubectl exec -n kube-system etcd-master02 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.242:2379 member add master01 https:/192.168.10..241:2380 #查看etcd集群已有节点 kubectl exec -n kube-system etcd-master02 -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://192.168.10.242:2379 member list #启动kube-apiserver、kube-controller-manager、kube-scheduler kubeadm init phase kubeconfig all --config k8s-init-master01.yaml kubeadm init phase control-plane all --config k8s-init-master01.yaml #标记节点为master kubectl get nodes #ROLES为none状态 kubeadm init phase mark-control-plane --config k8s-init-master01.yaml #ROLES为master状态 kubectl get nodes #ROLES为master状态 #查看恢复是否正常(如果失败,还需重新删除坏的etcd,然后再来一遍) kubectl get nodes #master01 status变成ready kubectl get pods --namespace kube-system -o wide #成功恢复 十四、安装helm(kubernetes的包管理器,教程是关于helm2的,helm3版本已发生改变,省掉了till端) #前提条件: 必须安装了kubernetes集群 必须拥有本地配置好的kubectl #安装client端(Helm CLI) #脚本安装 curl https://raw.githubusercontent.com/helm/helm/master/scripts/get > get_helm.sh chmod u+x get_helm.sh ./get_helm.sh #二进制安装 wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.0-linux-amd64.tar.gz tar -xzvf helm-v2.14.0-linux-amd64.tar.gz cp linux-amd64/helm /usr/local/bin/helm &&  cp linux-amd64/tiller /usr/local/bin/tiller #安装server端(tiller是服务端组件,会安装到kubernetes集群里) #安装ssl/tls的tiller(https://helm.sh/docs/using_helm/#using-ssl-between-helm-and-tiller) cd /etc/kubernetes/pki && mkdir helm cd helm #制作CA RSA私钥 openssl genrsa -out ./ca.key.pem 4096 #制作CA根证书 openssl req -key ca.key.pem -new -x509 -days 7300 -sha256 -out ca.cert.pem -extensions v3_ca -subj "/C=CN/O=HELM/CN=HELM" #生成tiller RSA私钥 openssl genrsa -out ./tiller.key.pem 4096 #生成helm RSA私钥 openssl genrsa -out ./helm.key.pem 4096 #生成tiller私钥的签名请求对(csr) openssl req -key tiller.key.pem -new -sha256 -out tiller.csr.pem -subj "/C=CN/O=HELM/CN=TILLER" #生成helm私钥的签名请求(csr) openssl req -key helm.key.pem -new -sha256 -out helm.csr.pem -subj "/C=CN/O=HELM/CN=HELM" #使用CA根证书对tiller的签名请求(csr)签名 #openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365 #默认情况下,Helm 客户端通过隧道(即 kube 代理)127.0.0.1 连接到 Tiller。 在 TLS 握手期间,通常提供主机名(例如 example.com),对证书进行检查,包括附带的信息。 但是,由于通过隧道,目标是 IP 地址。因此,要验证证书,必须在 Tiller 证书中将 IP 地址 127.0.0.1 列为 IP 附带备用名称(IP SAN: IP subject alternative name)。 例如,要在生成 Tiller 证书时将 127.0.0.1 列为 IP SAN: echo subjectAltName=IP:127.0.0.1 > extfile.cnf openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem -days 365 -extfile extfile.cnf #使用CA根证书对helm的签名请求(csr)签名 openssl x509 -req -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in helm.csr.pem -out helm.cert.pem  -days 365 #查看证书内容命令 openssl x509 -text -noout -in tiller.cert.pem #初始化tiller(注意helm客户端版本要跟服务端tiller images版本兼容) cd ~ helm version(注意helm客户端版本要跟服务端tiller images版本兼容) #无安全认证 helm init --history-max=0 --debug --upgrade --service-account tiller  --tiller-namespace kube-system --tiller-image gcr.azk8s.cn/google_containers/tiller:v2.14.0 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts #启用TLS安全认证(后续教程启用了TLS) helm init --history-max=0 --debug --upgrade --service-account tiller  --tiller-namespace kube-system --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.0 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts --tiller-tls --tiller-tls-cert /etc/kubernetes/pki/helm/tiller.cert.pem --tiller-tls-key /etc/kubernetes/pki/helm/tiller.key.pem --tiller-tls-verify --tls-ca-cert /etc/kubernetes/pki/helm/ca.cert.pem #使用谷歌默认地址,可能网络不通(https://kubernetes-charts.storage.googleapis.com) helm init --history-max=0 --debug --upgrade --service-account tiller  --tiller-namespace kube-system --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.0 --tiller-tls --tiller-tls-cert /etc/kubernetes/pki/helm/tiller.cert.pem --tiller-tls-key /etc/kubernetes/pki/helm/tiller.key.pem --tiller-tls-verify --tls-ca-cert /etc/kubernetes/pki/helm/ca.cert.pem #kubernetes上给tiller新建账户和角色(helm-tiller.yaml详见同级目录的helm-tiller.yaml) kubectl apply -f helm-tiller.yaml #kubectl delete -f helm-tiller.yaml #查看授权是否成功 kubectl get deploy --namespace kube-system   tiller-deploy  --output yaml | grep serviceAccount #配置client tls #执行 helm ls 会报错:Error: transport is closing,这是因为您的 Helm 客户端没有正确的证书来向 Tiller 进行身份验证。 helm ls --debug helm ls --tls --tls-ca-cert /etc/kubernetes/pki/helm/ca.cert.pem --tls-cert /etc/kubernetes/pki/helm/helm.cert.pem --tls-key /etc/kubernetes/pki/helm/helm.key.pem --debug #更快捷的方式是 \cp -f /etc/kubernetes/pki/helm/ca.cert.pem $HOME/.helm/ca.pem \cp -f /etc/kubernetes/pki/helm/helm.cert.pem $HOME/.helm/cert.pem \cp -f /etc/kubernetes/pki/helm/helm.key.pem  $HOME/.helm/key.pem helm ls --tls --debug #验证 helm version --tls --debug kubectl get pods -n kube-system | grep tiller kubectl -n kube-system get deployment kubectl logs $(kubectl get pods -n kube-system | grep tiller | awk '{print $1}') -n kube-system #查看服务 kubectl get svc  -n kube-system | grep tiller #验证端口 kubectl get pods tiller-deploy-c595846c-vf4vr --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}' -n kube-system #如何删除和重置 kubectl delete deployment tiller-deploy -n kube-system kubectl delete service tiller-deploy -n kube-system kubectl delete -f helm-tiller.yaml rm -rf $HOME/.helm 或者 helm reset -f --tls && helm reset --remove-helm-home --tls(存在无法连接tiller pod,reset失败的情况,只能使用上面的办法删除) #使用helm helm search helm repo list helm repo update helm list --tls #因为kubernetes集群开启了rbac,所以安装的时候需要创建rbac权限 helm install stable/nginx-ingress  --name nginx-ingress --tls --debug --set rbac.create=true #查看状态 helm status nginx-ingress --tls 十五、使用kubectl,对rc、deployment方式部署的pod进行滚动更新或者回滚 # 如果你使用ReplicationController创建的pod可以使用kubectl rollingupdate命令滚动升级,如果使用的是Deployment创建的Pod可以直接修改yaml文件后执行kubectl apply即可。 # Deployment已经内置了RollingUpdate strategy,因此不用再调用kubectl rollingupdate命令,升级的过程是先创建新版的pod将流量导入到新pod上后销毁原来的旧的pod。 # Rolling Update适用于Deployment、Replication Controller,官方推荐使用Deployment而不再使用Replication Controller。 # 要在没有中断的情况下更新服务,请kubectl支持所谓的滚动更新,它一次更新一个容器,而不是同时关闭整个服务。 Replication Controller方式: # 在线更新 kubectl rolling-update NAME NEW_NAME --image=IMAGE:TAG or kubectl rolling-update NAME -f FILE # 遇到问题后,回滚 kubectl rolling-update my-nginx --rollback deployment方式: # 范例 1、新建deployment:webserver,replicas=10,image=tomcat。 2、滚动更新应用镜像为:nginx kubectl path deployment webserver -p '{"spec":{"temple":{"spec:{"containers":[{"name":"webserver","image":"nginx"}]}"}}}' 3、观察Replicasets的变化,可发现升级后会创建新的Replicasets,删除老的Replicasets实例,滚动创建新实例。 十六、使用kubeadm方式进行kubernetes版本升级 #https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade-1-15/ #https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/ #https://github.com/kubernetes/kubeadm/issues/1322 #https://github.com/kubernetes/kubernetes/pull/69366 #https://juejin.im/post/5c9ce517e51d452b837c959e #获取最新kubeadm最新版本 yum list --showduplicates kubeadm --disableexcludes=kubernetes #升级第一个控制节点(master01执行) #安装最新版本kubeadm yum install -y kubeadm-1.15.0-0 --disableexcludes=kubernetes #验证下载是否有效并具有预期版本 kubeadm version #获取升级计划 kubeadm upgrade plan #选择要升级到的版本,然后运行相应的命令 kubeadm upgrade apply v1.15.0 #手动升级您的CNI提供程序插件 #按需操作 #升级控制端上的kubelet和kubectl yum install -y kubelet-1.15.0-0 kubectl-1.15.0-0 --disableexcludes=kubernetes #重启kubelet systemctl restart kubelet #升级其他控制节点(其他master节点执行) #与第一个控制节点操作相同但使用: kubeadm upgrade node 代替 kubeadm upgrade apply #查看kubeadm-config kubectl -n kube-system get cm kubeadm-config -oyaml #编辑添加内容 ClusterStatus: | nodeRegistration: criSocket: /var/run/dockershim.sock apiEndpoints: master01: advertiseAddress: 192.168.10.241 bindPort: 6443 master02: advertiseAddress: 192.168.10.242 bindPort: 6443 master03: advertiseAddress: 192.168.10.243 bindPort: 6443 apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterStatus #如果没有上面内容则执行kubeadm upgrade node会报错: unable to fetch the kubeadm-config ConfigMap: failed to get node registration: node master02 doesn't have kubeadm.alpha.kubernetes.io/cri-socket annotation unable to fetch the kubeadm-config ConfigMap: failed to getAPIEndpoint: failed to get APIEndpoint information for this node #升级工作节点(node节点执行) #安装最新版本kubeadm yum install -y kubeadm-1.15.0-0 --disableexcludes=kubernetes #排空node节点(master端执行) #通过将有负载的节点标记为不可调度并逐出工作负载来准备节点以进行维护 kubectl drain node01 --ignore-daemonsets #升级kubelet配置 kubeadm upgrade node #升级kubelet和kubectl yum install -y kubelet-1.15.x-0 kubectl-1.15.x-0 --disableexcludes=kubernetes #重启kubelet systemctl restart kubelet #恢复节点(master端执行) kubectl uncordon node01 十七、kubeadm证书有效期问题 # https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/ # https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/ kubeadm 默认证书为一年,一年过期后,会导致api service不可用,使用过程中会出现:x509: certificate has expired or is not yet valid kubeadm部署的kubernets证书一直都是个诟病,默认都只有一年有效期,kubeadm 1.14.x安装后有部分证书还是一年有效期,但个别证书已修改为10年有效期,但对我们使用来说,一年有效期还是一个比较的坑,需要进行调整。 修改kubeadm 1.14.x源码,调整证书过期时间 kubeadm1.14.x 安装过后crt证书如下所示 /etc/kubernetes/pki/apiserver.crt /etc/kubernetes/pki/front-proxy-ca.crt         #10年有效期 /etc/kubernetes/pki/ca.crt                     #10年有效期 /etc/kubernetes/pki/apiserver-etcd-client.crt /etc/kubernetes/pki/front-proxy-client.crt     #10年有效期 /etc/kubernetes/pki/etcd/server.crt /etc/kubernetes/pki/etcd/ca.crt                #10年有效期 /etc/kubernetes/pki/etcd/peer.crt              #10年有效期 /etc/kubernetes/pki/etcd/healthcheck-client.crt /etc/kubernetes/pki/apiserver-kubelet-client.crt 如上所示,除了标注说明的证书为10年有效期,其余都是1年有效期,我们查看下原先调整证书有效期的源码,克隆kubernetes 源码,切换到1.14.1 tag 查看: 代码目录: staging/src/k8s.io/client-go/util/cert/cert.go # 那么解决方法大致两种: 一种,调整证书有效期,重新编译:http://team.jiunile.com/blog/2018/12/k8s-kubeadm-ca-upgdate.html # 修改证书有效期为10年 # github下载kubernetes1.14.8版本 # 所有版本都需要修改的 vim cmd/kubeadm/app/util/pkiutil/pki_helpers.go NotAfter:     time.Now().Add(duration365d).UTC(), 改为 NotAfter:     time.Now().Add(duration365d * 10).UTC(), # 1.14.0以前版本额外需要修改的 vim staging/src/k8s.io/client-go/util/cert/cert.go NotAfter:     time.Now().Add(duration365d).UTC(), 改为 NotAfter:     time.Now().Add(duration365d * 10).UTC(), NotAfter:  time.Now().Add(time.Hour * 24 * 365), 改为 NotAfter:  time.Now().Add(time.Hour * 24 * 3650), # 使用官方容器编译kubeadm docker pull mirrorgooglecontainers/kube-cross:v1.12.10-1 docker run -it --rm -v /appservice/kubernetes-1.14.8:/go/src/k8s.io/kubernetes mirrorgooglecontainers/kube-cross:v1.12.10-1 /bin/sh cd /go/src/k8s.io/kubernetes # 编译kubeadm, 这里主要编译kubeadm即可 make all WHAT=cmd/kubeadm GOFLAGS=-v # 补充参考 # # 编译kubelet #     make all WHAT=cmd/kubelet GOFLAGS=-v # # 编译kubectl #     make all WHAT=cmd/kubectl GOFLAGS=-v # 编译产物在容器目录/go/src/k8s.io/kubernetes/_output/bin/kubeadm下,或者/go/src/k8s.io/kubernetes/_output/local/bin/linux/amd64下 # 在挂载目录/appservice/kubernetes-1.14.8/_output/local/bin/linux/amd64下 # 退出容器 exit # 备份原先kubeadm命令,然后使用新的替换 cp /usr/bin/kubeadm /usr/bin/kubeadm.$(date +%Y%m%d%H%M) \ && cp /appservice/kubernetes-1.14.8/_output/local/bin/linux/amd64/kubeadm /usr/bin/kubeadm 二种,重新签发证书: #建议不要重新生成ca证书,因为更新了ca证书,集群节点就需要手工操作,才能让集群正常(会涉及重新join) #操作之前,先将/etc/kubernetes/pki下的证书文件,mv到其它文件夹,作个临时备份,不要删除。 kubeadm alpha phase certs etcd-healthcheck-client --config cluster.yaml kubeadm alpha phase certs etcd-peer --config cluster.yaml kubeadm alpha phase certs etcd-server --config cluster.yaml kubeadm alpha phase certs front-proxy-client--config cluster.yaml kubeadm alpha phase certs apiserver-etcd-client --config cluster.yaml kubeadm alpha phase certs apiserver-kubelet-client --config cluster.yaml kubeadm alpha phase certs apiserver --config cluster.yaml kubeadm alpha phase certs sa --config cluster. # 查看证书有效期 cd /etc/kubernetes/pki openssl x509 -in ca.crt -noout -dates openssl x509 -in apiserver.crt -noout -dates openssl x509 -in apiserver-kubelet-client.crt -noout -dates openssl x509 -in front-proxy-ca.crt -noout -dates openssl x509 -in front-proxy-client.crt -noout -dates # etcd openssl x509 -in etcd/ca.crt -noout -dates openssl x509 -in etcd/etcd.crt -noout -dates # 1.8 kubelet版本及以上证书轮换 #https://kubernetes.io/zh/docs/tasks/tls/certificate-rotation/ Kubelet 使用证书进行 Kubernetes API 的认证。 默认情况下,这些证书的签发期限为一年,所以不需要太频繁地进行更新。 Kubernetes 1.8 版本中包含 beta 特性 kubelet 证书轮换, 在当前证书即将过期时, 将自动生成新的秘钥,并从 Kubernetes API 申请新的证书。 一旦新的证书可用,它将被用于与 Kubernetes API 间的连接认证。 # 启用客户端证书轮换 kubelet 进程接收 --rotate-certificates 参数,该参数决定 kubelet 在当前使用的证书即将到期时, 是否会自动申请新的证书。 由于证书轮换是 beta 特性,必须通过参数 --feature-gates=RotateKubeletClientCertificate=true 进行启用。 kube-controller-manager 进程接收 --experimental-cluster-signing-duration 参数,该参数控制证书签发的有效期限。 十八、使用外部etcd集群(仅供步骤参考,细节需要自己适配更改) # 安装etcd yum install -y etcd # 使用kubeadm生成etcd的ca证书 # 生成etcd的ca证书 kubeadm init phase certs etcd-ca --config k8s-init-master09.yaml # 或者根据配置生成所有证书 kubeadm init phase certs all --config k8s-init-master09.yaml # 以下是docker内etcd集群才会用到 # kubeadm init phase certs etcd-server --config k8s-init-master09.yaml # kubeadm init phase certs etcd-peer --config k8s-init-master09.yaml # kubeadm init phase certs etcd-healthcheck-client --config k8s-init-master09.yaml # kubeadm init phase certs apiserver-etcd-client --config k8s-init-master09.yaml # kubeadm init phase etcd local --config k8s-init-master09.yaml # 创建所有服务的证书 cd /etc/etcd/ mkdir ssl cd ssl cp /etc/kubernetes/pki/etcd/ca.* ./ # 已有ca根证书 # CA RSA私钥 ca.key # CA根证书 ca.crt # 生成etcd RSA私钥 openssl genrsa -out ./etcd.key 4096 # 生成etcd私钥的签名请求对(csr) openssl req -key etcd.key -new -sha256 -out etcd.csr -subj "/C=CN/O=ETCD/CN=ETCD" # 使用制作的CA根证书对每个签名请求(csr)签名 echo "subjectAltName=DNS:master09,IP:10.0.10.9,IP:127.0.0.1" > extfile openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in etcd.csr -extfile extfile -out etcd.crt -days 3650 # 10年 # 补充查看命令 openssl x509 -text -noout -in etcd.crt # 将etcd.key,etcd.crt复制到/etc/kubernetes/pki/etcd下 cp etcd.* /etc/kubernetes/pki/etcd/ # 修改etcd数据目录软链到存储上 mv /var/lib/etcd /appservice/ ln -s /appservice/etcd /var/lib/etcd # 修改etcd配置 grep -v ^# /etc/etcd/etcd.conf ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="https://10.0.10.9:2380" ETCD_LISTEN_CLIENT_URLS="https://localhost:2379,https://10.0.10.9:2379" ETCD_NAME="master09" ETCD_INITIAL_ADVERTISE_PEER_URLS="https://10.0.10.9:2380" ETCD_ADVERTISE_CLIENT_URLS="https://10.0.10.9:2379" ETCD_INITIAL_CLUSTER="master09=https://10.0.10.9:2380" ETCD_ENABLE_V2="false" ETCD_CERT_FILE="/etc/etcd/ssl/etcd.crt" ETCD_KEY_FILE="/etc/etcd/ssl/etcd.key" ETCD_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.crt" ETCD_PEER_CERT_FILE="/etc/etcd/ssl/etcd.crt" ETCD_PEER_KEY_FILE="/etc/etcd/ssl/etcd.key" ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.crt" # 启动并设置开机启动 systemctl start etcd systemctl enable etcd # 注意修改k8s-init-master.yaml中的etcd配置 etcd: external: endpoints: - https://10.0.10.9:2379 caFile: /etc/kubernetes/pki/etcd/ca.crt certFile: /etc/kubernetes/pki/etcd/etcd.crt keyFile: /etc/kubernetes/pki/etcd/etcd.key