部署一套完整的kubernetes高可用集群(上)

根据阿良老师的微信公众号文章<部署一套完整的Kubernetes高可用集群>抄写
自己添加了根据centos8和自己实践中的一些东西
入门来自k8s in action 和 qq群,现在依旧是菜鸟

一. 前置知识点
1.1 生产环境可部署k8s集群的两种方式
目前生产部署k8s集群主要有两种方式:

  • kubeadm
    kubeadm是一个k8s部署工具, 提供kubeadmn init和kubeadm join 两种方式, 用于快速部署k8s集群
    官方地址: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
  • 二进制包
    从github上下载发行版的二进制包,手动部署每个组件,组成k8s集群.
    kubeadm降低部署门槛, 但是屏蔽了很多细节, 遇到问题很难排查.如果想要容易可控,推荐使用二进制包部署k8s集群,虽然手动部署麻烦点,但是期间可以学习很多工作原理,也有利于后期维护.

1.2 安装要求
在开始之前,部署k8s集群机器需要满足一下几个条件:

  • 一台或多台机器, 操作系统centos8.x-86_x64
  • 硬件配置:2GB或更多RAM, 2个CPU或者更多cpu,硬盘三十G或者更多
  • 集群中所有机器之间网络互通
  • 可以访问外网, 需要拉取镜像, 如果服务器不能上网,需要提前下载镜像并导入节点
  • 禁止swap分区
    1.3 准备环境
    软件环境:
软件版本
操作系统Centos8.2_x64
k8s1.18
Docker19-ce

服务器整体规划:

角色IP组件
k8s-master1192.168.31.71kube-apiserver, kube-controller-manager, kube-scheduler, etcd
k8s-master2192.168.31.74kube-apiserver, kube-controller-manager, kube-scheduler, etcd
k8s-node1192.168.31.72kubelet, kube-proxy, docker, etcd
k8s-node2192.168.31.73kubelet, kube-proxy, docker, etcd
nginx-master192.168.31.76, 192.168.31.75(vip)Nginx L4
nginx-slave192.168.31.77Nginx L4

须知: 考虑到有些朋友电脑配置较低, 这么多虚拟机跑不动, 所以一套高可用集群分为两部分实施, 现部署一套Master架构(192.168.31.71,72,73),再扩容为多Master架构(上述规划), 顺便熟悉一下Master扩容流程

单Master架构图
单Master架构图
对k8s集群架构进行说明:

  • 主节点: 它承载着k8s控制和管理整个集群系统的控制面板
  • 工作节点:他们主要运行用户实际部署的应用
    控制面板
    控制面板用于控制集群并使他工作.它包含多个组件,组件可以运行在单个主节点或者通过副本分别部署在多个主节点以确保可用性. 这些组件是:
  • Kubernetes API服务器, 你和其他控制面板组件都要和他通信
  • Scheduler,他调度你的应用(为应用的每个可部署组件分配一个工作节点)
  • Controller Manager,他执行集群级别的功能, 如复制组件,持续跟踪工作节点,处理结点失败等.
  • etcd,一个可靠的分布式数据存储, 他能持久化存储集群设置
    工作节点
    工作节点是运行容器化应用的机器.运行,监控和管理应用服务的任务是通过一下组件来完成的:
  • Docker,rtk或其他容器类型
  • Kubelet, 他与API服务器通信,并管理他所在节点的容器
  • kubernetes Service Proxy(kube-proxy),他负责组件之间的负载均衡网络流量

单Master服务器规划

角色ip组件
k8s-master192.168.31.71kube-apiserver, kube-controller-manager, kube-scheduler, etcd
k8s-node1192.168.31.72kube-proxy, kubelet,docker, etcd
k8s-node2192.168.31.73kube-proxy,kubelet,docker,etcd

1.4 操作系统初始化设置

#使用root用户
su -
#关闭防火墙
systemctl stop  firewalld.service
#禁止防火墙开机启动
systemctl disable firewalld.service
#永久关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/conf
#暂时关闭selinux
setenforce 0
#暂时关闭swap
swapoff -a
#永久关闭swap
sed -ri 's'/.*swap*./#&' /etc/fstab #意思是将包含swap的行直接注释
#根据规划设置主机名
hostnamectl set-hostname <hostname>

#在master添加hosts
cat >> /etc/hosts <<EOF #表示新建一个文件以EOF作为结束标志
192.168.31.71 mk8s-master
192.168.31.72 mk8s-node1
192.168.31.73 mk8s-node2
EOF
# 修改网络地址
nmcli connection modify ens33 \
connection.autoconnect yes  \
ipv4.method manual  \
ipv4.dns 192.168.31.2  \ 
ipv4.gateway 192.168.31.2  \
ipv4.addresses 192.168.31.71/24 
#修改网络地址实际生效
nmcli connection up ens33

#将桥接的IPV4流量转接到iptables的链
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
EOF
#生效
sysctl --system

#时间同步--在centos8中
#注释掉 pool 2.centos.pool.ntp.org iburst
sed -ri 's/pool 2.centos.pool.ntp.org iburst/#&/' /etc/chrony.conf 
#添加新的时间同步服务器
vim /etc/chrony.conf
server 210.72.145.44 iburst
server ntp.aliyun.com iburst
#时间同步
chronyc sources -v
#配置开机启动
systemctl enable chronyd.service

------------------2020.11.30------------------------------------------

其中关于将桥接的ipv4流量桥接到iptables的链的说明(不懂):

如果net.bridge.bridge-nf-call-iptables=1,也就意味着二层的网桥在转发包时也会被iptables的FORWARD规则所过滤,这样就会出现L3层的iptables rules去过滤L2的帧的问题

二.部署Etcd集群

  • K8s如何使用etcd

我们创建的所有对象pod,ReplicationController,服务,私密凭证等,需要以持久化的方式存储某个地方,这样他们的manifest在API服务器重启和失败的时候才不会丢失,为此,k8s使用了etcd.

etcd是一个响应快,分布式,一致的key-value存储. 因为他是分布式的,故而可以运行多个实例来获取高可用性和更好的性能.

唯一能直接和etcd通信的是k8s的API服务器,所有其他组件通过API服务器间接的读取,写入数据到etcd.这带来一些好处,其中之一就是增强乐观锁系统,验证系统的健壮性;并且通过把实际存储机制从其他组件抽离,未来替换起来也比较容易.值得强调的是etcd是k8s集群存储集群状态和元数据的唯一的地方.

Etcd是一个分布式键值存储系统,k8s使用etcd进行数据存储,所以先准备一个Etcd数据库,为了解决Etcd单点故障问题, 应该采用集群部署, 这里使用三台组件集群, 可以容忍一台机器故障,当然,你也可以使用5台组件集群,可以容忍两台机器故障.

节点名称ip
etcd-1192.168.31.71
etcd-2192.168.31.72
etcd-3192.168.31.73

注意这里为了节省机器,这里与k8s节点机器复用.也可以独立于k8s集群之外部署,只要apiserver能连接到即可.
API服务器是与etcd通信的唯一组件,其他组件不会直接与etcd通信而是通过API服务器来修改集群状态.

2.1 准备cfssl证书生成工具
cfssl是CloudFlare开源的一个证书管理工具, 使用JSON文件生成证书,相比openssl更加方便使用.
CFSSL包含一个命令行工具和一个用于签名,验证并且捆绑TLS证书的HTTP API服务. 使用go编写.

  1. 集群相关证书类型
    client certificate: 用于服务端认证客户端,例如etcdctl,etcd proxy, fleetctl,docker客户端
    server certificate: 服务端使用,客户端以此认证服务端身份, 例如docker服务端, kube-apiserver
    peer certificate:双向证书, 用于etcd集群成员之间通信

  2. 根据认证对象可以将证书分为三类: 服务端证书server cert, 客户端client cert以及对等证书 peer cert(表示既是server cert又是client cert),在k8s集群中需要的证书种类如下:

    • etcd 节点需要标识自己服务的server cert,也需要client cert与etcd集群中其他节点交互, 当然可以分别指定2个证书,也可以使用一个peer对等证书
    • master节点需要标识api-server的server cert,也需要client cert连接etcd集群, 这里也使用一个对等证书
    • kubectl calico kube-proxy 只需要client cert,因此证书中hosts字段可以为空
    • kubelet证书比较特殊, 不是手动生成,他由node节点TLS Bootstrap向apiserver请求,由master节点的controller-manager自动签发,包含一个client cert和一个server cert
  3. 找任意一台服务器操作, 这里使用Master节点

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo

2.2 生成etcd证书

  1. 自签证书颁发机构(CA)
  • 创建工作目录
mkdir -p ~/TLS/{etcd,k8s}
cd TLS/etcd
  • 为自签CA生成默认配置文件与请求文件
cfssl print-defaults config > ca-config.json
cfssl print-defaults csr > ca-csr.json
  • 自定义自签CA
#配置证书生成策略,规定CA可以颁发哪些类型的证书
vim ca-config.json
{
    "signing": {
        "default": {
            "expiry": "87600h"
        },
        "profiles": {
            "www": {
                "expiry": "87600h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
		           "client auth"
                ]
            }
        }
    }
}
#创建CA证书签名请求
cat ca-csr.json
{
    "CN": "etcd CA",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]
}

知识点:

ca-config.json: 可以定义多个profiles(配置), 分别指定不同的过期时间(expiry),使用场景(usages)等参数;后续在签名证书时使用某个profile;本示例只有一个www的使用场景
signing:表示该证书可以签名其他证书,生成的ca.pem证书中CA=TRUE
server auth: 表示客户端可以用该CA对Server提供的证书进行验证
client auth:表示server可以用该CA对client提供的证书进行验证

ca-csr.json:
CN:common Name的意思, kube-apiserver从证书中提取该字段作为请求的用户名(User Name)
O:Organization,kube-apiserver从证书中提取该字段作为请求用户所属的组

  • 生成证书
    生成CA所必需的文件ca-key.pem(私钥)和ca.pem(证书),还会生成ca.csr(证书签名请求),用于交叉签名或重新签名
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
ls *pem
ca-key.pem ca.pem 
ls *csr
ca.csr

cfssljson只是整理json格式, -bare的主要意义在于,命名

  1. 使用自签CA签发etcd https证书

截止目前, 基于CFSSL的CA已经配置完成, 那么该CA如何颁发证书呢?CFSSL提供了两个命令:gencert和sign.gencert将自动处理整个证书生成过程.该过程需要两个文件, 一个告诉CFSSL本地客户端CA的位置以及如何验证请求,即config文件, 另一个为CSR配置信息,用于填充CSR即csr信息

  • 为etcd https证书生成默认证书请求文件
cfssl print-defaults csr > server-csr.json
  • 自定义证书请求文件
{
    "CN": "etcd",
    "hosts": [
        "192.168.31.71",
	"192.168.31.72",
	"192.168.31.73"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "L": "Beijing",
            "ST": "Beijing"
        }
    ]

}

注意: 上述文件hosts字段中IP为所有etcd节点的集群内部通信ip,一个都不能少!为了方便后续扩容可以多写几个预留的ip

hosts包含的是授权范围,不在此范围的节点或者服务使用此证书就会报服务不匹配错误. 如果hosts字段不为空则需要指定使用该证书的ip或者域名列表,由于该证书后续被etcd集群使用,所以制定了etcd集群的ip
hosts中的内容可以为空,即按照上面的配置, 向集群中添加新节点之后不需要重新生成证书

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config -profile=www server-csr.json | cfssljson -bare server
ls server*pem
server.pem server-key.pem
ls server*csr
server.csr

知识点:

-config引用的是自定义的证书配置文件, -profiles是指定特定的使用场景

  1. 创建etcd配置文件
cat > /opt/etcd/cfg/etcd.conf <<EOF
#[Member]
ETCD_NAME="etcd-1"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.31.71:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.31.71:2379"
#[Clustering ]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.31.71:2380"
ETCD_INITIAL_CLUSTER="etcd-1=https://192.168.31.71:2380, etcd-2=https://192.168.31.72:2380,etcd-2=https://192.168.31.73:2380"
ETCD_INITIAL_CLUSRER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.31.71:2379"

默认配置来源于: https://etcd.io/docs/v3.4.0/op-guide/configuration/

以下是对各个环境变量的说明

  • ETCD_NAME:节点名称, 集群中唯一;在官方文档中的解释为这个key(etcd-1)的值是在ETCD_INITIAL_CLUSTER中列出的URL列表
  • ETCD_DATA_DIR:数据目录;官方文档如是
  • ETCD_LISTEN_PEER_URLS:集群通信监听地址;在官方文档中的解释是:监听对等流量访问的url列表, 这个标志(环境变量)告诉etcd以指定的scheme://ip:port的组合接受来自他对等方的传入请求. 协议可以是http或者https.如果0.0.0.0吧被指定作为ip,etcd将会监听给定接口所有端口. 如果一个ip地址和port是给定的, etcd将会监听给定的端口和接口. 多个地址可能会用于指定去监听多个地址和端口. etcd将会回应所有被列出的地址和端口组合的请求
  • ETCD_LISTEN_CLINET_URLS:客户端访问监听地址;官方文档的解释是:监听客户端流量访问的url列表, 这个标志(环境变量)告诉etcd以指定的scheme://ip:port的组合接受来自他对等方的传入请求. 协议可以是http或者https.如果0.0.0.0吧被指定作为ip,etcd将会监听给定接口所有端口. 如果一个ip地址和port是给定的, etcd将会监听给定的端口和接口. 多个地址可能会用于指定去监听多个地址和端口. etcd将会回应所有被列出的地址和端口组合的请求
  • ETCD_INITIAL_ADVERTISE_PEER_URLS:集群通告地址;官方文档解释是:向集群中的其余成员发布本成员监听的对等url列表. 这些地址被用于集群中的etcd数据交流. 至少一个成员必须能够路由到集群中所有的成员. 这些url可以是域名
  • ETCD_INITIAL_CLUSTER:集群节点地址;官方文档的解释是ETCD_INITIAL_CLUSTER的值是每一个ETCD_NAME做key 的键值对的value,比如说ETCD_NAME=“default”,那么ETCD_INITIAL_CLUTSER=“default-1=http://localhost:2380”,注意由于是每一个结点, 因此可能会有default-2,default-3
  • ETCD_INITIAL_CLUSTER_TOKEN:集群TOKEN;官方文档亦是
  • ETCD_ADVERTISE_CLIENT_URLS:客户端通告地址;官方文档的解释是:向集群中其余成员发布本成员监听的客户端url列表.这些地址可以是域名
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值