前言:
如今兄弟们对“apiserver高可用”大概比较着重,看官们都需要学习一些“apiserver高可用”的相关文章。那么小编在网络上搜集了一些有关“apiserver高可用””的相关内容,希望同学们能喜欢,咱们快快来了解一下吧!本文因为头条排版问题,阅读不是很友好,可以私信联系作者获取源文档。
一、架构说明Kubernetes集群组件etcd 一个高可用的K/V键值对存储和服务发现系统flannel 实现跨主机的容器网络的通信kube-apiserver 提供kubernetes集群的API调用kube-controller-manager 确保集群服务kube-scheduler 调度容器,分配到Nodekube-proxy 提供网络代理服务kubeadm:用来初始化集群的指令。kubectl: 用来与集群通信的命令行工具。通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。kubelet 运行在集群中的每个节点上,用来启动 pod 和 container 等。
k8s集群高可用,一般是etcd、kube-apiserver、kube-controller-manager、kube-scheduler服务组件的高可用。
规划
3个master节点,2个worker节点,使用keepalived+haproxy做高可用
二、前期准备工作修改所有主机的hosts文件
cat >/etc/hosts<<EOF130.252.10.235 node1130.252.10.236 node2130.252.10.237 node3130.252.10.238 node4130.252.10.239 node5EOF同步时间
ntpdate time.windows.comhwclock --systohc禁用selinux,需要重启
setenforce 0sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinuxsed -i 's/^SELINUX=*/SELINUX=disabled/' /etc/selinux/config内核参数修改
cat <<EOF | sudo tee /etc/modules-load.d/k8s.confbr_netfilterEOFcat >> /etc/sysctl.d/k8s.conf <<EOFnet.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_nonlocal_bind = 1net.ipv4.ip_forward = 1vm.swappiness = 0EOFsysctl --systemLinux 节点上的 iptables 需要查看桥接流量,因此要将 net.bridge.bridge-nf-call-iptables 设置为 1,并且加载 br_netfilter 内核模块关闭系统swap
Kubernetes 1.8开始要求关闭系统的Swap,如果不关闭,默认配置下kubelet将无法启动。
方法一 通过kubelet的启动参数 –fail-swap-on=fals 更改这个限制方法二 关闭系统的swap
修改/etc/fstab文件,注释掉SWAP的自动挂载,使用free -m确认swap已经关闭。
swapoff -ased -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab关闭防火墙
生产环境不建议关闭防火墙
systemctl disable firewalld.servicesystemctl stop firewalld.service加载ipvs内核模块
modprobe -- nf_conntrack_ipv4 >/dev/null 2>&1if [ $? -eq 0 ];thennf_conntrack_module=nf_conntrack_ipv4elsenf_conntrack_module=nf_conntrackfi cat > /etc/sysconfig/modules/ipvs.modules <<EOF#!/bin/bashmodprobe -- ip_vsmodprobe -- ip_vs_rrmodprobe -- ip_vs_wrrmodprobe -- ip_vs_shmodprobe -- ${nf_conntrack_module}modprobe -- rbdEOFchmod 755 /etc/sysconfig/modules/ipvs.modulesbash /etc/sysconfig/modules/ipvs.modules三、安装Docker
yum-utils 提供yum-config-manager工具,devicemapper存储需要device-mapper-persistent-data和lvm2
yum install -y yum-utils device-mapper-persistent-data lvm2添加yum源仓库官方仓库
yum-config-manager --add-repo阿里仓库
yum-config-manager --add-repo安装Docker-ce
yum -y install docker-ce docker-ce-cli containerd.io
启动docker,设置开机启动docker
systemctl restart docker && \systemctl enable docker && \systemctl list-unit-files |grep docker
扩展:安装指定版本的docker
yum list docker-ce --showduplicates | sort -r #显示所有可用docker版本yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io官网安装:配置docker中国镜像加速
修改cgroup driver为systemd,k8s建议使用systemd,配置后重启docker
cat > /etc/docker/daemon.json <<EOF{"registry-mirrors": [";,";,";],"exec-opts": ["native.cgroupdriver=systemd"],"log-driver": "json-file","log-opts": {"max-file": "3","max-size": "100m"},"storage-driver": "overlay2","storage-opts": ["overlay2.override_kernel_check=true"]}EOF# 查看dockerdocker info# 重启systemctl restart docker安装参考
注意:所有节点都需要安装docker
四、安装haproxy和keepalived安装haproxy和keepalivedhaproxy和keepalived,实现kube-apiserver高可用psmisc提供killall命令
yum install keepalived haproxy psmisc ipvsadm -y配置haproxy
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bakcat > /etc/haproxy/haproxy.cfg <<EOFglobal log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/statsdefaults mode tcp log global option tcplog option dontlognull option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000listen stats mode http bind :10086 stats enable stats uri /admin?stats stats auth admin:admin stats admin if TRUEfrontend k8s_https *:8443 mode tcp maxconn 2000 default_backend https_sribackend https_sri balance roundrobin server s1 130.252.10.235:6443 check inter 2000 fall 3 rise 3 weight 1 server s2 130.252.10.236:6443 check inter 2000 fall 3 rise 3 weight 1 server s3 130.252.10.237:6443 check inter 2000 fall 3 rise 3 weight 1EOFhaproxy 在 10086 端口输出 status 信息;haproxy 监听所有接口的 8443 端口,该端口与环境变量 ${KUBE_APISERVER} 指定的端口必须一致;server 字段列出所有 kube-apiserver 监听的 IP 和端口;配置keepalived
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bakcat > /etc/keepalived/keepalived.conf <<EOF! Configuration File for keepalivedglobal_defs { script_user root enable_script_security router_id LVS_MASTER}vrrp_script check-haproxy { script "/usr/bin/killall -0 haproxy" interval 3 weight -30}vrrp_instance VI_kube-master { state MASTER interface ens32 virtual_router_id 60 dont_track_primary priority 120 advert_int 3 track_script { check-haproxy } authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 130.252.10.233 }}EOF
注意:在另外两个节点,设置state为BACKUP,priority分别设置为110和100
启动haproxy和keepalived
在所有节点启动
systemctl restart haproxy && \systemctl enable haproxy && \systemctl status haproxy systemctl restart keepalived && \systemctl enable keepalived && \systemctl status keepalived查看VIP注意,使用ifconfig命令是看不到的,必须使用ip addr命令
# ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 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 forever2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:25:f1:8d brd ff:ff:ff:ff:ff:ff inet 130.252.10.235/16 brd 130.252.255.255 scope global noprefixroute ens32 valid_lft forever preferred_lft forever inet 130.252.10.233/32 scope global ens32 valid_lft forever preferred_lft forever inet6 fe80::ece5:efc4:1cf1:2d7c/64 scope link noprefixroute valid_lft forever preferred_lft forever3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:88:7f:d3:1a brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever
这时候vip在130.252.10.235上,我们可以通过关闭235上的haproxy,来验证vip是否会漂移到其他节点
五、安装kubeadm、kubelet、kubectlkubeadm: 部署集群用的命令kubelet: 在集群中每台机器上都要运行的组件,负责管理pod、容器的生命周期kubectl: 集群管理工具(可选,只要在控制集群的节点上安装即可)添加kubernetes源
这里使用阿里云的kubernetes的yum源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=安装kubelet、kubeadm、kubectl
yum install -y kubelet kubeadm kubectlsystemctl enable kubelet && systemctl start kubelet注意:此时kubelet是无法启动的
注:所有的节点都要安装
六、使用kubeadm初始化cluster准备初始化配置文件
打印kubeadm默认的配置文件
kubeadm config print init-defaults > kubeadm-init.yaml
根据自己的环境修改配置
apiVersion: kubeadm.k8s.io/v1beta1bootstrapTokens:- groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authenticationkind: InitConfigurationlocalAPIEndpoint: advertiseAddress: 130.252.10.235 #本机IP bindPort: 6443 #监听端口nodeRegistration: criSocket: /var/run/dockershim.sock name: node1 taints: - effect: NoSchedule key: node-role.kubernetes.io/master---apiServer: timeoutForControlPlane: 4m0sapiVersion: kubeadm.k8s.io/v1beta1certificatesDir: /etc/kubernetes/pkiclusterName: kubernetescontrolPlaneEndpoint: "130.252.10.233:8443" #控制平面IP:VIP:端口controllerManager: {}dns: type: CoreDNSetcd: local: dataDir: /var/lib/etcdimageRepository: k8s.gcr.iokind: ClusterConfigurationkubernetesVersion: v1.14.3networking: dnsDomain: cluster.local podSubnet: "10.244.0.0/16" #POD网段 serviceSubnet: 10.96.0.0/12 #service网段scheduler: {}---apiVersion: kubeproxy.config.k8s.io/v1alpha1kind: KubeProxyConfigurationfeatureGates: SupportIPVSProxyMode: truemode: ipvs---apiVersion: kubelet.config.k8s.io/v1beta1kind: KubeletConfigurationfailSwapOn: falsecgroupDriver: systemd
说明:
advertiseAddress:API Server将要广播的监听地址bindPort:API Server绑定的端口,默认6443serviceSubnet:为service的虚拟IP地址另外指定IP地址段, 缺省值:10.96.0.0/12podSubnet:指明pod网络可以使用的IP地址段。 如果设置了这个参数,control plane将会为每一个节点自动分配CIDRskubeproxy配置段:通过kubeadm config print init-defaults --component-configs KubeProxyConfiguration命令打印来,从Kubernetes 1.11后,SupportIPVSProxyMode默认为truekubelet配置段非必须:可通过kubeadm config print init-defaults --component-configs KubeletConfiguration打印出配置,如果你开启了swap则需要配置failSwapOn: false,并使用kubeadm init --config kubeadm-init.yaml --ignore-preflight-errors=Swap命令初始化
注意:
podSubnet 一定要指定,不然后面flannel启动会失败
具体错误信息如下:Error registering network: failed to acquire lease: node "master1" pod cidr not assigned解决方法:
在/etc/kubernetes/manifests/kube-controller-manager.yaml 文件的command处加入下面两行- --allocate-node-cidrs=true
- --cluster-cidr=10.244.0.0/16或者使用kubeadm reset重新部署处理kubernetes依赖的镜像
master需要的镜像为
kube-apiserverkube-controller-managerkube-schedulerkube-proxycorednspauseetcdflannel
node节点需要的镜像为
kube-proxypauseflannel
查看需要的镜像版本
kubeadm config images list --kubernetes-version=v1.14.3
拉取镜像,此步骤不需要,除非你能访问谷歌
kubeadm config images pull
一般情况,我们通过阿里云镜像服务拉取kubernetes所需要的镜像,然后再重新tag
初始化第一个master节点
注意:如果你禁用了swap分区,则不需要加--ignore-preflight-errors=Swap
# kubeadm init --config kubeadm-init.yaml --ignore-preflight-errors=Swap[init] Using Kubernetes version: v1.14.3[preflight] Running pre-flight checks [WARNING Swap]: running with swap on is not supported. Please disable swap[preflight] Pulling images required for setting up a Kubernetes cluster[preflight] This might take a minute or two, depending on the speed of your internet connection[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"[kubelet-start] Activating the kubelet service[certs] Using certificateDir folder "/etc/kubernetes/pki"[certs] Generating "front-proxy-ca" certificate and key[certs] Generating "front-proxy-client" certificate and key[certs] Generating "etcd/ca" certificate and key[certs] Generating "etcd/server" certificate and key[certs] etcd/server serving cert is signed for DNS names [node1 localhost] and IPs [130.252.10.235 127.0.0.1 ::1][certs] Generating "apiserver-etcd-client" certificate and key[certs] Generating "etcd/healthcheck-client" certificate and key[certs] Generating "etcd/peer" certificate and key[certs] etcd/peer serving cert is signed for DNS names [node1 localhost] and IPs [130.252.10.235 127.0.0.1 ::1][certs] Generating "ca" certificate and key[certs] Generating "apiserver" certificate and key[certs] apiserver serving cert is signed for DNS names [node1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 130.252.10.235 130.252.10.233][certs] Generating "apiserver-kubelet-client" certificate and key[certs] Generating "sa" key and public key[kubeconfig] Using kubeconfig folder "/etc/kubernetes"[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address[kubeconfig] Writing "admin.conf" kubeconfig file[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address[kubeconfig] Writing "kubelet.conf" kubeconfig file[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address[kubeconfig] Writing "controller-manager.conf" kubeconfig file[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address[kubeconfig] Writing "scheduler.conf" kubeconfig file[control-plane] Using manifest folder "/etc/kubernetes/manifests"[control-plane] Creating static Pod manifest for "kube-apiserver"[control-plane] Creating static Pod manifest for "kube-controller-manager"[control-plane] Creating static Pod manifest for "kube-scheduler"[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s[kubelet-check] Initial timeout of 40s passed.[apiclient] All control plane components are healthy after 42.007732 seconds[upload-config] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace[kubelet] Creating a ConfigMap "kubelet-config-1.14" in namespace kube-system with the configuration for the kubelets in the cluster[upload-certs] Skipping phase. Please see --experimental-upload-certs[mark-control-plane] Marking the node node1 as control-plane by adding the label "node-role.kubernetes.io/master=''"[mark-control-plane] Marking the node node1 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule][bootstrap-token] Using token: abcdef.0123456789abcdef[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster[bootstrap-token] creating the "cluster-info" ConfigMap in the "kube-public" namespace[addons] Applied essential addon: CoreDNS[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address[addons] Applied essential addon: kube-proxyYour Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/configYou should now deploy a pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: can now join any number of control-plane nodes by copying certificate authoritiesand service account keys on each node and then running the following as root: kubeadm join 130.252.10.233:8443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:4d95989174b67c857bed7313750e021f07ec56beb2e6e764c7ef2de5645187e9 \ --experimental-control-plane Then you can join any number of worker nodes by running the following on each as root:kubeadm join 130.252.10.233:8443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:4d95989174b67c857bed7313750e021f07ec56beb2e6e764c7ef2de5645187e9
说明:
如果初始化时指定了 --upload-certs参数,即使用了kubeadm init --config kubeadm-init.yaml --upload-certs --ignore-preflight-errors=Swap命令来初始化,则不需要手动将证书文件复制到其他节点(第八步操作)--upload-certs:用于将应在所有控制平面实例之间共享的证书上载到群集
初始化过程:
[init]:指定版本进行初始化操作[preflight] :初始化前的检查和下载所需要的Docker镜像文件[kubelet-start] :生成kubelet的配置文件”/var/lib/kubelet/config.yaml”,没有这个文件kubelet无法启动,所以初始化之前的kubelet实际上启动失败。[certificates]:生成Kubernetes使用的证书,存放在/etc/kubernetes/pki目录中。[kubeconfig] :生成 KubeConfig 文件,存放在/etc/kubernetes目录中,组件之间通信需要使用对应文件。[control-plane]:使用/etc/kubernetes/manifest目录下的YAML文件,安装 Master 组件。[etcd]:使用/etc/kubernetes/manifest/etcd.yaml安装Etcd服务。[wait-control-plane]:等待control-plan部署的Master组件启动。[apiclient]:检查Master组件服务状态。[uploadconfig]:更新配置[kubelet]:使用configMap配置kubelet。[patchnode]:更新CNI信息到Node上,通过注释的方式记录。[mark-control-plane]:为当前节点打标签,打了角色Master,和不可调度标签,这样默认就不会使用Master节点来运行Pod。[bootstrap-token]:生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到[addons]:安装附加组件CoreDNS和kube-proxy配置kubectl
mkdir -p $HOME/.kubecp -i /etc/kubernetes/admin.conf $HOME/.kube/configchown $(id -u):$(id -g) $HOME/.kube/config启用kubectl命令自动补全
安装bash-completion
yum install bash-completion -y
说明:
bash-completion 负责导入 /etc/bash_completion.d 目录中的所有补全脚本。
重新加载shell后,运行命令type _init_completion检查bash-completion是否安装成功
配置kubeclt自动补全
方法一在文件~/.bashrc中导入补全脚本:
echo 'source <(kubectl completion bash)' >>~/.bashrc方法二将补全脚本添加到目录/etc/bash_completion.d中:
kubectl completion bash >/etc/bash_completion.d/kubectl
注意:
建议使用方法二。方法一会导致shell脚本执行source ~/.bashrc时,出错。
参考:
七、安装Pod网络flannel
kubectl apply -fflannel 网络插件不部署,coredns一直处于pending状态。
官网链接:
八、将其他master节点添加到cluster同步证书文件到其他master节点
将node1证书文件复制到其他master节点node2,node3
for host in node2 node3doecho ">>>>>>>>>>>>>>>>>>>>$host<<<<<<<<<<<<<<<<<<<<<"ssh $host "mkdir -p /etc/kubernetes/pki/etcd"scp /etc/kubernetes/pki/ca.* $host:/etc/kubernetes/pki/scp /etc/kubernetes/pki/sa.* $host:/etc/kubernetes/pki/scp /etc/kubernetes/pki/front-proxy-ca.* $host:/etc/kubernetes/pki/scp /etc/kubernetes/pki/etcd/ca.* $host:/etc/kubernetes/pki/etcd/scp /etc/kubernetes/admin.conf $host:/etc/kubernetes/done将其他master加入集群
查看master的token
kubeadm token list | grep authentication,signing | awk '{print $1}'
查看discovery-token-ca-cert-hash
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
注意:token有效期是有限的,如果旧的token过期,可以使用kubeadm token create --print-join-command重新创建一条token。
分别在master1和master2 执行下面的命令来加入集群,注意要修改token和ca-cert-hash为上面查询出来的结果
kubeadm join 130.252.10.233:8443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:4d95989174b67c857bed7313750e021f07ec56beb2e6e764c7ef2de5645187e9 \--experimental-control-plane --ignore-preflight-errors=Swapmkdir -p $HOME/.kubecp -i /etc/kubernetes/admin.conf $HOME/.kube/configchown $(id -u):$(id -g) $HOME/.kube/config九、将node节点添加到cluster
kubeadm join 130.252.10.233:8443 --token abcdef.0123456789abcdef \--discovery-token-ca-cert-hash sha256:4d95989174b67c857bed7313750e021f07ec56beb2e6e764c7ef2de5645187e9 \--ignore-preflight-errors=Swap十、检查集群运行健康查看节点状态
# kubectl get nodesNAME STATUS ROLES AGE VERSIONnode1 Ready master 15m v1.14.3node2 Ready master 12m v1.14.3node3 Ready master 10m v1.14.3node4 Ready <none> 25s v1.14.3node5 Ready <none> 2m34s v1.14.3# kubectl get csNAME STATUS MESSAGE ERRORscheduler Healthy ok controller-manager Healthy ok etcd-0 Healthy {"health":"true"}
所有的节点都是NotReady,这是因为每个节点都需要启动若干组件,这些组件都是在pod中运行,需要从Google下载镜像
查看pod的状态
# kubectl get pod --all-namespaces -o wideNAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESkube-system coredns-fb8b8dccf-7hdvh 1/1 Running 0 16m 10.244.0.4 node1 <none> <none>kube-system coredns-fb8b8dccf-xcn94 1/1 Running 0 16m 10.244.0.5 node1 <none> <none>kube-system etcd-node1 1/1 Running 0 15m 130.252.10.235 node1 <none> <none>kube-system etcd-node2 1/1 Running 0 13m 130.252.10.236 node2 <none> <none>kube-system etcd-node3 1/1 Running 0 11m 130.252.10.237 node3 <none> <none>kube-system kube-apiserver-node1 1/1 Running 0 15m 130.252.10.235 node1 <none> <none>kube-system kube-apiserver-node2 1/1 Running 0 13m 130.252.10.236 node2 <none> <none>kube-system kube-apiserver-node3 1/1 Running 0 11m 130.252.10.237 node3 <none> <none>kube-system kube-controller-manager-node1 1/1 Running 1 16m 130.252.10.235 node1 <none> <none>kube-system kube-controller-manager-node2 1/1 Running 0 13m 130.252.10.236 node2 <none> <none>kube-system kube-controller-manager-node3 1/1 Running 0 11m 130.252.10.237 node3 <none> <none>kube-system kube-flannel-ds-amd64-dkfhr 1/1 Running 0 11m 130.252.10.237 node3 <none> <none>kube-system kube-flannel-ds-amd64-j2v7w 1/1 Running 0 96s 130.252.10.238 node4 <none> <none>kube-system kube-flannel-ds-amd64-mm82s 1/1 Running 0 14m 130.252.10.235 node1 <none> <none>kube-system kube-flannel-ds-amd64-n9fbw 1/1 Running 0 3m45s 130.252.10.239 node5 <none> <none>kube-system kube-flannel-ds-amd64-psv22 1/1 Running 2 13m 130.252.10.236 node2 <none> <none>kube-system kube-proxy-56wc5 1/1 Running 0 11m 130.252.10.237 node3 <none> <none>kube-system kube-proxy-fqf5x 1/1 Running 0 3m45s 130.252.10.239 node5 <none> <none>kube-system kube-proxy-k8v9v 1/1 Running 0 16m 130.252.10.235 node1 <none> <none>kube-system kube-proxy-mt9g6 1/1 Running 0 13m 130.252.10.236 node2 <none> <none>kube-system kube-proxy-r88kh 1/1 Running 0 96s 130.252.10.238 node4 <none> <none>kube-system kube-scheduler-node1 1/1 Running 1 16m 130.252.10.235 node1 <none> <none>kube-system kube-scheduler-node2 1/1 Running 0 13m 130.252.10.236 node2 <none> <none>kube-system kube-scheduler-node3 1/1 Running 0 11m 130.252.10.237 node3 <none> <none>
Pending、ContainerCreating、ImagePullBackOff 都表明Pod没有就绪,Running才是就绪
所有的服务都变成了集群状态,etcd,kube-apiserver,kube-controller-manager,kube-scheduler服务每个master节点都启动一个Pod
查看集群信息
# kubectl cluster-infoKubernetes master is running at is running at further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.查看etcd集群
查看集群是否健康
# docker run --rm -it --net host \-v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:3.3.10 etcdctl \--cert-file /etc/kubernetes/pki/etcd/peer.crt \--key-file /etc/kubernetes/pki/etcd/peer.key \--ca-file /etc/kubernetes/pki/etcd/ca.crt \--endpoints cluster-healthmember 1625c8dc0eff006e is healthy: got healthy result from a78e5b84db62da12 is healthy: got healthy result from be5e1657d6a1f8de is healthy: got healthy result from is healthy
查看集群的leader
# docker run --rm -it --net host \-v /etc/kubernetes:/etc/kubernetes k8s.gcr.io/etcd:3.3.10 etcdctl \--cert-file /etc/kubernetes/pki/etcd/peer.crt \--key-file /etc/kubernetes/pki/etcd/peer.key \--ca-file /etc/kubernetes/pki/etcd/ca.crt \--endpoints member list1625c8dc0eff006e: name=node1 peerURLs= clientURLs= isLeader=truea78e5b84db62da12: name=node2 peerURLs= clientURLs= isLeader=falsebe5e1657d6a1f8de: name=node3 peerURLs= clientURLs= isLeader=false
注意:
因为是3个节点的ETCD集群,所以只能有1个宕机,如果同时有2个节点宕机,则会出现问题Unable to connect to the server: EOF
ETCD集群需要大多数节点(仲裁)才能就集群状态的更新达成一致,所以ETCD集群节点一般是奇数个,而且只有存活节点数大于下线节点数 才能正常运行,5个节点的ETCD集群,允许同时2个节点故障。
一般建议5个节点,超过5个虽然容错性更高,但是集群写入性就会差。假如etcd实例的总数超过了这个数目。那么多出来的节点(peers)将会以独立(standbys)的方式启动,假如集群中一个活跃的节点挂掉或者被移除掉,那么这些多出来的单独启动的节点将会增加到活跃集群中
检查IPVS
# ipvsadm -lnIP Virtual Server version 1.2.1 (size=4096)Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port Forward Weight ActiveConn InActConnTCP 10.96.0.1:443 rr-> 130.252.10.235:6443 Masq 1 0 0 -> 130.252.10.236:6443 Masq 1 0 0 -> 130.252.10.237:6443 Masq 1 0 1 TCP 10.96.0.10:53 rrTCP 10.96.0.10:9153 rrUDP 10.96.0.10:53 rr查看当前系统配置
# kubectl get cm -n kube-system kubeadm-config -o yamlapiVersion: v1data: ClusterConfiguration: | apiServer: extraArgs: authorization-mode: Node,RBAC timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta1 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controlPlaneEndpoint: 130.252.10.233:8443 controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.14.3 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 scheduler: {} ClusterStatus: | apiEndpoints: node1: advertiseAddress: 130.252.10.235 bindPort: 6443 node2: advertiseAddress: 130.252.10.236 bindPort: 6443 node3: advertiseAddress: 130.252.10.237 bindPort: 6443 apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterStatuskind: ConfigMapmetadata: creationTimestamp: "2019-06-19T08:56:47Z" name: kubeadm-config namespace: kube-system resourceVersion: "1034" selfLink: /api/v1/namespaces/kube-system/configmaps/kubeadm-config uid: 2b62d002-9270-11e9-a471-000c2925f18d
可以看到apiEndpoints有3个
kube-proxy配置
# kubectl get cm -n kube-system kube-proxy -oyamlapiVersion: v1data: config.conf: |- apiVersion: kubeproxy.config.k8s.io/v1alpha1 bindAddress: 0.0.0.0 clientConnection: acceptContentTypes: "" burst: 10 contentType: application/vnd.kubernetes.protobuf kubeconfig: /var/lib/kube-proxy/kubeconfig.conf qps: 5 clusterCIDR: 10.244.0.0/16 configSyncPeriod: 15m0s conntrack: max: null maxPerCore: 32768 min: 131072 tcpCloseWaitTimeout: 1h0m0s tcpEstablishedTimeout: 24h0m0s enableProfiling: false featureGates: SupportIPVSProxyMode: true healthzBindAddress: 0.0.0.0:10256 hostnameOverride: "" iptables: masqueradeAll: false masqueradeBit: 14 minSyncPeriod: 0s syncPeriod: 30s ipvs: excludeCIDRs: null minSyncPeriod: 0s scheduler: "" strictARP: false syncPeriod: 30s kind: KubeProxyConfiguration metricsBindAddress: 127.0.0.1:10249 mode: ipvs nodePortAddresses: null oomScoreAdj: -999 portRange: "" resourceContainer: /kube-proxy udpIdleTimeout: 250ms winkernel: enableDSR: false networkName: "" sourceVip: "" kubeconfig.conf: |- apiVersion: v1 kind: Config clusters: - cluster: certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt server: ; name: default contexts: - context: cluster: default namespace: default user: default name: default current-context: default users: - name: default user: tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/tokenkind: ConfigMapmetadata: creationTimestamp: "2019-06-19T08:56:51Z" labels: app: kube-proxy name: kube-proxy namespace: kube-system resourceVersion: "244" selfLink: /api/v1/namespaces/kube-system/configmaps/kube-proxy uid: 2dbcf684-9270-11e9-a471-000c2925f18d
kubelet-config
# kubectl get cm -n kube-system kubelet-config-1.14 -oyamlapiVersion: v1data: kubelet: | address: 0.0.0.0 apiVersion: kubelet.config.k8s.io/v1beta1 authentication: anonymous: enabled: false webhook: cacheTTL: 2m0s enabled: true x509: clientCAFile: /etc/kubernetes/pki/ca.crt authorization: mode: Webhook webhook: cacheAuthorizedTTL: 5m0s cacheUnauthorizedTTL: 30s cgroupDriver: cgroupfs cgroupsPerQOS: true clusterDNS: - 10.96.0.10 clusterDomain: cluster.local configMapAndSecretChangeDetectionStrategy: Watch containerLogMaxFiles: 5 containerLogMaxSize: 10Mi contentType: application/vnd.kubernetes.protobuf cpuCFSQuota: true cpuCFSQuotaPeriod: 100ms cpuManagerPolicy: none cpuManagerReconcilePeriod: 10s enableControllerAttachDetach: true enableDebuggingHandlers: true enforceNodeAllocatable: - pods eventBurst: 10 eventRecordQPS: 5 evictionHard: imagefs.available: 15% memory.available: 100Mi nodefs.available: 10% nodefs.inodesFree: 5% evictionPressureTransitionPeriod: 5m0s failSwapOn: false fileCheckFrequency: 20s hairpinMode: promiscuous-bridge healthzBindAddress: 127.0.0.1 healthzPort: 10248 httpCheckFrequency: 20s imageGCHighThresholdPercent: 85 imageGCLowThresholdPercent: 80 imageMinimumGCAge: 2m0s iptablesDropBit: 15 iptablesMasqueradeBit: 14 kind: KubeletConfiguration kubeAPIBurst: 10 kubeAPIQPS: 5 makeIPTablesUtilChains: true maxOpenFiles: 1000000 maxPods: 110 nodeLeaseDurationSeconds: 40 nodeStatusReportFrequency: 1m0s nodeStatusUpdateFrequency: 10s oomScoreAdj: -999 podPidsLimit: -1 port: 10250 registryBurst: 10 registryPullQPS: 5 resolvConf: /etc/resolv.conf rotateCertificates: true runtimeRequestTimeout: 2m0s serializeImagePulls: true staticPodPath: /etc/kubernetes/manifests streamingConnectionIdleTimeout: 4h0m0s syncFrequency: 1m0s volumeStatsAggPeriod: 1m0skind: ConfigMapmetadata: creationTimestamp: "2019-06-19T08:56:47Z" name: kubelet-config-1.14 namespace: kube-system resourceVersion: "150" selfLink: /api/v1/namespaces/kube-system/configmaps/kubelet-config-1.14 uid: 2b656b6f-9270-11e9-a471-000c2925f18d
这里虽然看的的是cgroupfs,但是kubelet启动时会读取/var/lib/kubelet/kubeadm-flags.env文件,此文件中已经指定了cgroupDriver为systemd,通过systemctl status kubelet我们也可以看的
验证集群高可用
为了验证高可用,我们可以关闭其中的master节点,查看是否生效。注意节点关闭后40s后,节点才会被标注为NotReady状态。5分钟后驱逐节点上的Pod
参考etcd
标签: #apiserver高可用