k8s 高可用 2 个核心 apiserver master 和 etcd
etcd:(需高可用)集群的数据中心, 用于存放集群的配置以及状态信息, 非常重要, 如果数据丢失那么集群将无法恢复; 因此高可用集群部署首先就是 etcd 是高可用集群;
Apiserver: 提供了资源操作的唯一入口, 并提供认证, 授权, 访问控制, API 注册和发现等机制. 整个集群中其他角色只有通过 Apiserver 才能访问 etcd.CLI 工具 kubectl 也是通过 apiserver 来对整体集群进行访问控制.
Controller-manager: 负责维护集群的状态, 比如故障检测, 自动扩展, 滚动更新等. 一组 k8s master 上同一时间只有一个 controller-manager 角色进行工作, 因为要避免控制冲突.
Scheduler: 负责资源的调度, 按照预定的调度策略将 Pod 调度到相应的机器上. 一组 k8s master 上同一时间只有一个 scheduler 角色进行工作, 同样因为要避免控制冲突.
Kubelet: 负责维护容器的生命周期, 同时也负责 Volume(CVI)和网络 (CNI) 的管理. 为支持 k8s master 的高可用, 由 kubelet 提供稳定的容器运行功能(static pod), 通过运行容器的方式启动
kube-proxy: 每个 node 上一个, 负责 service vip 到 endpoint pod 的流量转发, 老版本主要通过设置 iptables 规则实现, 新版 1.9 基于 kube-proxy-lvs 实现
集群网络结构:
网络名称 | 网络范围 |
SVC 网络 | 172.20.0.0/16 |
集群网络 | 172.21.0.0/16 |
物理网络 | 192.168.10.0/24 |
节点构造如下 :
节点 ip | 节点角色 | hostname |
192.168.10.7 | node | node1 |
192.168.10.8 | node | node2 |
192.168.10.9 | master01+etcd | master1 |
192.168.10.10 | master02+etcd | master2 |
192.168.10.11 | master03+etcd | master3 |
由所有 master 节点提供一组 VIP:192.168.10.6 用来高可用
环境初始化
1. 安装之前关闭防火墙和 selinux
- systemctl stop firewalld
- systemctl disable firewalld
- [root@test ~]# getenforce
- Disabled
2. 所有节点需要设定 / etc/sysctl.d/k8s.conf 的系统参数.
- cat <<EOF> /etc/sysctl.d/k8s.conf
- net.bridge.bridge-nf-call-ip6tables = 1
- net.bridge.bridge-nf-call-iptables = 1
- EOF
- sysctl -p
安装 docker
- yum install -y yum-utils device-mapper-persistent-data lvm2 net-tools conntrack-tools wget vim ntpdate libseccomp libtool-ltdl
- yum -y install docker
systemctl enable docker && systemctl start docker
1. 创建 etcd 高可用集群:
kuberntes 系统使用 etcd 存储所有数据, 本文档介绍部署一个三节点高可用 etcd 集群的步骤, 这三个节点复用 kubernetes master 机器
搭建 etcd 集群需要注意的是 etcd 最少需要三台才能发挥其高可用的功能, 因为 etcd 集群内部使用的是选举制度, 通过内部选举一台 Leader, 而如果当集群内部主机少于三台时, etcd 的 Leader 选举功能就出现问题, 导致 Leader 选举失败, 从而 etcd 不能正常与外界通讯
- yum -y install etcd
- vim /etc/etcd/etcd.conf
- #[Member]
- ETCD_NAME="etcd1"
- ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
- ETCD_LISTEN_PEER_URLS="http:// 当前服务器 IP:2380"
- ETCD_LISTEN_CLIENT_URLS="http:// 当前服务器 IP:2379,http://127.0.0.1:2379"
- #[Clustering]
- ETCD_INITIAL_ADVERTISE_PEER_URLS="http:// 当前服务器 IP:2380"
- ETCD_ADVERTISE_CLIENT_URLS="http:// 当前服务器 IP:2379"
- ETCD_INITIAL_CLUSTER="etcd1=http://192.168.10.9:2380,etcd2=http://192.168.10.10:2380,etcd3=http://192.168.10.11:2380"
- ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
- ETCD_INITIAL_CLUSTER_STATE="new"
- vim /usr/lib/systemd/system/etcd.service // 修改 etcd 启动文件
- WorkingDirectory=/var/lib/etcd/
- EnvironmentFile=-/etc/etcd/etcd.conf
? 指定 etcd 的工作目录为 /var/lib/etcd, 数据目录为 /var/lib/etcd, 需在启动服务前创建这两个目录;
? 注意三台 etcd 的配置文件中 ETCD_NAME 的配置, 这里三台分别设置的是 etcd1,etcd2,etcd3.
启动 etcd 服务:
待三台 etcd 都搭建完成之后, 可依次启动(在 etcd 集群中如果只单独启动一台 etcd 会出现报错)
- [root@master01 ~]# systemctl daemon-reload
- [root@master01 ~]# systemctl start etcd
- [root@master01 ~]# systemctl enable etcd
验证集群服务:
[root@test ~]# etcdctl --endpoints=http://192.168.10.9:2379,http://192.168.10.10:2379,http://192.168.10.11:2379 cluster-health
member 8c632555af4d958d is healthy: got healthy result from http://192.168.10.10:2379
member bc34c6bd673bdf9f is healthy: got healthy result from http://192.168.10.11:2379
member ec065b41856af137 is healthy: got healthy result from http://192.168.10.9:2379
- cluster is healthy
- [root@test ~]# 集群启动正常
2. 搭建 k8s_master 高可用集群
集群 HA 方案, 我们可以用 lvs 或者 nginx 做 4 层 lb 负载
安装 ipvsadm 管理工具
- yum -y install ipvsadm
- systemctl enable ipvsadm
配置 LVS 负载均衡服务
步骤 1: 在 eth0 网卡绑定 VIP 地址 (虚拟 ip) 要能和本地通信, 所以在同一网络 / 24 位
第一种方式:(重启服务器失效, 多用于临时测试)
ip add add/del 192.168.10.6/24 dev ens33
第二种: 修改配置文件(重启也生效)
- cp ifcfg-ens33 ifcfg-ens33:0
- vim ifcfg-ens33:0
- DEVICE=eth0:0 // 虚拟网络接口
- ONBOOT=yes // 系统启动时激活
- BOOTPROTO=static // 使用静态 ip 地址
- IPADDR=192.168.10.6 // 该虚拟网络接口的 ip
- NETMASK=255.255.255.0 // 子网掩码, 对应 ip 别名
- GATEWAY=192.168.10.1 // 网关, 对应 ip 别名
- HWADDR=00:10:5A:5E:B1:E4 // 网卡 MAC 地址, 无需更改
- USERCTL=no // 是否给予非 root 用户设备管理权限
配置完成重启网卡即可:
systemctl restart network
步骤 2: 清除当前所有 LVS 规则(-C)
ipvsadm -C
步骤 3: 设置 tcp,tcpfin,udp 链接超时时间(--set)
ipvsadm --set 30 5 60
表示 tcp 空闲等待时间为 30 秒
客户端关闭链接等待时间为 5 秒
udp 空闲等待为 60 秒
步骤 4: 添加虚拟服务(-A),-t 指定虚拟服务的 IP 端口,-s 指定调度算法 wrr 权重轮询 -p 指定会话保持时间
ipvsadm -A -t 192.168.10.6:8080 -s wrr -p 300(默认 300s)
步骤 5: 将虚拟服务关联到真实服务上(-a) -t 说明是 tcp 服务 -r 指定真实服务的 IP 端口 -g LVS 的 DR 模式 -w 指定权重
- ipvsadm -a -t 192.168.10.6:8080 -r 192.168.10.9:8080 -g -w 1
- ipvsadm -a -t 192.168.10.6:8080 -r 192.168.10.10:8080 -g -w 1
- ipvsadm -a -t 192.168.10.6:8080 -r 192.168.10.11:8080 -g -w 1
保存配置: 服务启动的时候会读取 / etc/sysconfig/ipvsadm 里面的内容, 并且逐行执行, 否则启动 ipvsadm 失败.
- ipvsadm-save> /etc/sysconfig/ipvsadm
- systemctl restart ipvsadm
步骤 6: 查看配置结果(-ln)
- ipvsadm -ln
- [root@lvs ~]# ipvsadm -ln
- IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
- TCP 192.168.10.6:8080 wrr persistent 300
- -> 192.168.10.9:8080 Route 3 0 0
- -> 192.168.10.10:8080 Route 3 6 0
- -> 192.168.10.11:8080 Route 3 7 0
- [root@lvs ~]#
Master 安装:
下载最新的二进制版本 https://github.com/kubernetes/kubernetes/releases/latest 并解压缩. 安装包下载: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.10.md#server-binaries
找到./kubernetes/server/kubernetes-server-linux-amd64.tar.gz 并解压缩那个. 然后在解压缩文件中, 找到./kubernetes/server/bin 包含所有必需的二进制文件的文件.
部署 k8s 遇到的问题: http://time-track.cn/deploy-kubernetes-in-ubuntu-14-04.html
我们也可以根据名称直接从 git 上下载服务端所需要的组件(推荐)
用 https 协议下载会报错, 以不安全的方式连接至 dl.k8s.io, 使用 "--no-check-certificate"
- mkdir /opt/soft
- cd /opt/soft
- wget https://dl.k8s.io/v1.10.3/kubernetes-server-linux-amd64.tar.gz --no-check-certificate
- tar -zxf kubernetes-server-linux-amd64.tar.gz
- cd /opt/soft/kubernetes/server/bin
- cp kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/bin/
开始创建 master 端主配置文件
配置文件参数详解: https://blog.csdn.net/levy_cui/article/details/70229818
- mkdir -p /etc/kubernetes
- cd /etc/kubernetes/
- vim config
- #/etc/kubernetes/config 文件同时被 kube-apiserver,kube-controller-manager,kube-scheduler,kubelet,kube-proxy 使用, 在 master 主机上的 config 配置文件中的 KUBE_MASTER 需要填写本机的 IP 地址, 而 node 端的则需要填写负载均衡的 VIP.
- KUBE_LOGTOSTDERR="--logtostderr=true" #日志默认存储方式, 默认存储在系统的 journal 服务中, 设置为 true 后日志不输出到文件
- KUBE_LOG_LEVEL="--v=0" #日志等级
- KUBE_ALLOW_PRIV="--allow-privileged=false" #如果设置为 true, 则 k8s 将允许在 pod 中运行拥有系统特权的容器应用, 与 docker run --privileged 的功效相同
- KUBE_MASTER="--master=http://192.168.10.9:8080" #kubernetes Master 的 apiserver 地址和端口
- vim apiserver: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
- KUBE_API_ADDRESS="--address=0.0.0.0" #aipServer 的监听地址, 默认为 127.0.0.1, 若要配置集群, 则要设置为 0.0.0.0 才能被其他主机找到
- #KUBE_API_PORT="--port=8080" #apiserver 的监听端口, 默认 8080 是用于接收 http 请求, 6443 用于接收 https 请求. 可以不用写
- #KUBELET_PORT="--kubelet_port=10250" # kubelet 的监听端口, 若只作为 Master 节点则可以不配置
- KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=172.20.0.0/16" # service 的地址范围, 用于创建 service 的时候自动生成或指定 serviceIP 使用
- KUBE_ETCD_SERVERS="--etcd-servers=http://192.168.10.9:2379,http://192.168.10.10:2379,http://192.168.10.11:2379" #etcd 地址
- KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota" #为了避免做用户认证, 取消掉了 ServiceAccount 参数
- KUBE_API_ARGS="--service-node-port-range=1-65535 --apiserver-count=3 --audit-log-maxage=30 --audit-log-maxbackup=3 --audit-log-maxsize=400 --audit-log-path=/var/lib/audit.log --event-ttl=1h" #此处可以添加其他配置
- vim controller-manager: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/
- KUBE_CONTROLLER_MANAGER_ARGS="--leader-elect=true --address=127.0.0.1"
? --address 值必须为 127.0.0.1, 因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器;
- vim scheduler: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/
- KUBE_SCHEDULER_ARGS="--leader-elect=true --address=127.0.0.1"
? --address 值必须为 127.0.0.1, 因为当前 kube-apiserver 期望 scheduler 和 controller-manager 在同一台机器;
创建 kube-apiserver 的启动配置文件: vim /usr/lib/systemd/system/kube-apiserver.service
- [Unit]
- Description=Kubernetes API Server
- Documentation= https://github.com/GoogleCloudPlatform/kubernetes
- After=network.target
- After=etcd.service
- [Service]
- EnvironmentFile=-/etc/kubernetes/config
- EnvironmentFile=-/etc/kubernetes/apiserver
- ExecStart=/usr/bin/kube-apiserver \
- $KUBE_LOGTOSTDERR \
- $KUBE_LOG_LEVEL \
- $KUBE_ETCD_SERVERS \
- $KUBE_API_ADDRESS \
- $KUBE_API_PORT \
- $KUBE_ALLOW_PRIV \
- $KUBE_SERVICE_ADDRESSES \
- $KUBE_ADMISSION_CONTROL \
- $KUBE_API_ARGS
- Restart=on-failure
- Type=notify
- LimitNOFILE=65536
- [Install]
- WantedBy=multi-user.target
创建 kube-controller-manager 的启动配置文件: vim /usr/lib/systemd/system/kube-controller-manager.service
- [Unit]
- Description=Kubernetes Controller Manager
- Documentation= https://github.com/GoogleCloudPlatform/kubernetes
- [Service]
- EnvironmentFile=-/etc/kubernetes/config
- EnvironmentFile=-/etc/kubernetes/controller-manager
- ExecStart=/usr/bin/kube-controller-manager \
- $KUBE_LOGTOSTDERR \
- $KUBE_LOG_LEVEL \
- $KUBE_MASTER \
- $KUBE_CONTROLLER_MANAGER_ARGS
- Restart=on-failure
- LimitNOFILE=65536
- [Install]
- WantedBy=multi-user.target
创建 kube-scheduler 的启动配置文件: vim /usr/lib/systemd/system/kube-scheduler.service
- [Unit]
- Description=Kubernetes Scheduler Plugin
- Documentation= https://github.com/GoogleCloudPlatform/kubernetes
- [Service]
- EnvironmentFile=-/etc/kubernetes/config
- EnvironmentFile=-/etc/kubernetes/scheduler
- ExecStart=/usr/bin/kube-scheduler \
- $KUBE_LOGTOSTDERR \
- $KUBE_LOG_LEVEL \
- $KUBE_MASTER \
- $KUBE_SCHEDULER_ARGS
- Restart=on-failure
- LimitNOFILE=65536
- [Install]
- WantedBy=multi-user.target
启动服务(三台服务都搭建完成之后先启动 etcd 然后在启动其他服务):
- [root@master01 ~]# systemctl daemon-reload
- [root@master01 ~]# systemctl start etcd kube-apiserver kube-controller-manager kube-scheduler
- [root@master01 ~]# systemctl enable etcd kube-apiserver kube-controller-manager kube-scheduler
至此, kubernetes master 端的组件已经搭建完成, 我们在三台 master 主机上重复以上搭建步骤, 注意配置文件中需要修改 IP 地址的地方, 以及需要先启动 etcd, 然后依次启动 kube-apiserver,kube-controller-manager,kube-scheduler.
验证 master 节点功能: kubectl get cs
- [root@test ~]# kubectl get cs
- NAME STATUS MESSAGE ERROR
scheduler Healthy ok
- controller-manager Healthy ok
- etcd-0 Healthy {"health": "true"}
- etcd-1 Healthy {"health": "true"}
- etcd-2 Healthy {"health": "true"}
Node 安装:
每一台都搭建 flanneld,docker,kubelet,kube-proxy 这四个组件及服务
kubelet 是 Master 在 Node 节点上的 Agent, 管理本机运行容器的生命周期, 比如创建容器, Pod 挂载数据卷, 下载 secret, 获取容器和节点状态等工作. kubelet 将每个 Pod 转换成一组容器.
kube-proxy 在 Node 节点上实现 Pod 网络代理, 维护网络规则和四层负载均衡工作.
- scp kubelet kube-proxy root@192.168.10.7:/usr/bin/
- scp kubelet kube-proxy root@192.168.10.8:/usr/bin/
- yum -y install docker flannel
- vim /etc/sysconfig/flanneld
- FLANNEL_ETCD_ENDPOINTS="http://192.168.10.9:2379,http://192.168.10.10:2379,http://192.168.10.11:2379" #flannel 从 etcd 中读取配置
- FLANNEL_ETCD_PREFIX="/coreos.com/network" #/ http://coreos.com/network 是 master 端 etcd 网络授权的文件, 这个需要在启动 flanneld 之前在 master 端手动生成
- FLANNEL_OPTIONS="-iface=ens33"
在 master 端生成网络授权文件 / http://coreos.com/network :
etcdctl --endpoints=http://192.168.10.9:2379,http://192.168.10.10:2379,http://192.168.10.11:2379 mk / http://coreos.com/network /config '{"Network":"172.21.0.0/16"}'
查看是否添加成功
etcdctl get / http://coreos.com/network/config
如果 etcd 不是集群可以用下面的命令:
创建 node 端主配置文件:
- mkdir /etc/kubernetes
- vim /etc/kubernetes/config
- KUBE_LOGTOSTDERR="--logtostderr=true"
- KUBE_LOG_LEVEL="--v=0"
- KUBE_ALLOW_PRIV="--allow-privileged=false"
- KUBE_MASTER="--master=http://192.168.10.6:8080" #这里的 master 地址是负载均衡的 VIP 地址
创建 kubelet 服务配置文件:
- vim /etc/kubernetes/kubelet
- KUBELET_ADDRESS="--address=192.168.10.7"
- KUBELET_HOSTNAME="--hostname-override=192.168.10.7"
- KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image= http://registry.access.redhat.com/rhel7/pod-infrastructure:latest"
- KUBELET_ARGS="--fail-swap-on=false --cgroup-driver=systemd --enable-server=true --enable-debugging-handlers=true --kubeconfig=/var/lib/kubelet/kubeconfig --cluster-dns=172.20.0.100 --cluster-domain=cluster.local. --hairpin-mode promiscuous-bridge --serialize-image-pulls=false"
Kubernetes v1.8+ 要求关闭系统 Swap, 若不关闭则需要修改 kubelet 设定参数 --fail-swap-on=false
然后还要添加一个配置文件, 因为 1.9.0 在 kubelet 里不再使用 KUBELET_API_SERVER 来跟 API 通信, 而是通过别一个 yaml 的配置来实现, 描述了 kubelet 访问 apiserver 的方式.
参考: https://www.58jb.com/html/180.html
- mkdir -p /var/lib/kubelet
- vim /var/lib/kubelet/kubeconfig
- apiVersion: v1
- kind: Config
- users:
- - name: kubelet
- clusters:
- - name: kubernetes
- cluster:
- server: http://192.168.10.6:8080
- contexts:
- - context:
- cluster: kubernetes
- user: kubelet
- name: service-account-context
- current-context: service-account-context
创建 kubelet 启动 service 配置文件:
- vim /usr/lib/systemd/system/kubelet.service
- [Unit]
- Description=Kubernetes Kubelet Server
- Documentation= https://github.com/GoogleCloudPlatform/kubernetes
- After=docker.service
- Requires=docker.service
- [Service]
- WorkingDirectory=/var/lib/kubelet
- EnvironmentFile=-/etc/kubernetes/config
- EnvironmentFile=-/etc/kubernetes/kubelet
- ExecStart=/usr/bin/kubelet \
- $KUBE_LOGTOSTDERR \
- $KUBE_LOG_LEVEL \
- $KUBELET_API_SERVER \
- $KUBELET_ADDRESS \
- $KUBELET_PORT \
- $KUBELET_HOSTNAME \
- $KUBE_ALLOW_PRIV \
- $KUBELET_POD_INFRA_CONTAINER \
- $KUBELET_ARGS
- Restart=on-failure
- [Install]
- WantedBy=multi-user.target
创建 kube-proxy 服务配置文件:
- vim /etc/kubernetes/proxy
- KUBE_PROXY_ARGS="--proxy-mode=userspace --bind-address=0.0.0.0 --hostname-override=192.168.10.7"
创建 kube-proxy 启动 service 配置文件
- vim /usr/lib/systemd/system/kube-proxy.service
- [Unit]
- Description=Kubernetes Kube-Proxy Server
- Documentation= https://github.com/GoogleCloudPlatform/kubernetes
- After=network.target
- [Service]
- EnvironmentFile=-/etc/kubernetes/config
- EnvironmentFile=-/etc/kubernetes/proxy
- ExecStart=/usr/bin/kube-proxy \
- $KUBE_LOGTOSTDERR \
- $KUBE_LOG_LEVEL \
- $KUBE_MASTER \
- $KUBE_PROXY_ARGS
- Restart=on-failure
- LimitNOFILE=65536
- [Install]
- WantedBy=multi-user.target
启动服务
systemctl daemon-reload
systemctl start flanneld kubelet kube-proxy docker
systemctl enable flanneld kubelet kube-proxy docker
查看节点是否获取到
- [root@test ~]# kubectl get svc
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 16h
- [root@test ~]# kubectl get nodes
- NAME STATUS ROLES AGE VERSION
- 192.168.10.7 Ready <none> 16h v1.10.3
- 192.168.10.8 Ready <none> 16h v1.10.3
- [root@test ~]#
- OK!
来源: http://www.bubuko.com/infodetail-2622123.html