Centos下安装K3S+Rancher

文章目录

  • Centos下安装K3S+Rancher
    • 1. 准备工作
      • 1.1. disable firewall
      • 1.2. disable selinux
      • 1.3. disable swap(仅列出,可以暂不执行,效果不明)
      • 1.4. 修改主机名,并修改hosts
      • 1.5. 安装docker
        • 1.5.1. 修改Docker loglimit。非常重要!
        • 1.5.2. 修改Docker limit。非常重要!
        • 1.5.3. 强制使用overlay2存储引擎
        • 1.5.4. 修改docker数据目录(可选)
        • 1.5.5. 重启docker
      • 1.6. 节点优化(可选)
    • 2. 集群数据库方案
      • 2.1 使用etcd(推荐)
      • 2.2 使用mysql双机热备(实验性)
        • 2.2.1 准备工作
        • 2.2.2 正式安装
          • 2.2.2.1 修改配置文件
          • 2.2.2.2 正式启动容器,映射端口、my.cnf、data存放目录.
          • 2.2.2.3 设置主主
            • 2.2.2.3.1 先设置(节点1)->(节点2)的主从
            • 2.2.2.3.2 设置(节点2)->(节点1)的主从
    • 3. 高可用网络配置
      • 3.1. 安装nginx(可选)
      • 3.2. 安装keepalived
    • 4. 安装K3S
      • 打节点标签(可选)
      • 一个需要了解的说明
    • 5. 安装并指定私有镜像库
      • 5.1. 安装私有镜像库(可选)
      • 5.2. 配置K3S Server连接到私有镜像库
    • 6. 高可用安装Rancher
      • 6.1. 准备rancher 2.4.10 以及相关的docker镜像
      • 6.2. 准备Rancher Server证书
        • 6.2.1. 从DBU人员手中获取证书
        • 6.2.2. 自建证书
          • 6.2.2.1. 将Charts仓库和镜像仓库的根证书加入到自建根证书(可选)
        • 6.2.3. 使用已经签发好的证书(可选)
      • 6.3. 准备Helm和rancher 2.4.10 charts
        • 6.3.1. 下载Helm
        • 6.3.2. 拉取rancher charts
      • 6.4. 正式安装rancher
        • 6.4.1. 在K3S中创建rancher的命名空间
        • 6.4.2. 设置rancher server的证书
        • 6.4.3 最后一步,安装rancher
        • 6.4.4. 验证
      • 6.5. 配置通过IP直接访问多节点rancher(可选)
        • 6.5.1. 验证
    • 7. 设置keepalived检测脚本
    • 8. cattle-cluster-agent和cattle-node-agent几乎一定会处理的问题
      • 8.1. 域名解析问题
      • 8.2. Ingress导致的证书解析错误
      • 8.3. 某些CA证书无法验证,报X509错误
    • 结束
    • +1:完全离线安装
      • +1.1. 已经准备好的离线包(以标准centos为例,UOS特殊处理)
    • +2:在K3S集群加入一个Agent节点
      • +2.1. 节点环境准备
      • +2.2. 启动Agent节点
    • +3. 更换rancher的默认镜像库地址
    • +4. 删除rancher
    • +5. 修改ETCD节点信息
    • +6. 修改K3S_DATASTORE_ENDPOINT
    • +7. 高可用安装情况下修改80和443端口(本章节网上找不到,纯属原创精华)
    • +8. 在Rancher上手动创建Ingress
    • +9. 修改max-pods
    • +10. IP修改后,以灾难恢复方式重建ETCD

Centos下安装K3S+Rancher


’+1’章节:完全离线安装中需要用到的离线包在这里,提取码:h813


适用于centos7+,x86或arm都一样
在每个server节点上执行一次。

核心思想说明:

对于一个小型环境,因为k3s的server节点高可用,最少只需要2个节点(使用外部数据库)

对于中型环境,那么可以考虑更多的server节点,以及其他数据库方案(比如etcd、三节点galary mysql),方案上选择较多。


开始安装过程

以下工作以3台节点:172.16.149.122(k3s01),172.16.149.123(k3s02),172.16.149.124(k3s03),VIP172.16.149.139为例

1. 准备工作

每台机器上执行

1.1. disable firewall

systemctl stop firewalld
systemctl disable firewalld

1.2. disable selinux

setenforce 0
sed -i s#SELINUX=enforcing#SELINUX=disabled# /etc/selinux/config
重启机器

1.3. disable swap(仅列出,可以暂不执行,效果不明)

swapoff -a
# 找到fstab中,swap defaults那一行,行首加一个注释
sed -i ‘s/.*swap.defaults./#&/g’ /etc/fstab

1.4. 修改主机名,并修改hosts

hostnamectl set-hostname k3s01(节点2为k3s02)
echo -e “172.16.149.122\tk3s01” | tee -a /etc/hosts
echo -e “172.16.149.123\tks302” | tee -a /etc/hosts

1.5. 安装docker

用rancher提供的方式安装
curl https://releases.rancher.com/install-docker/19.03.sh | sh
|
或者用docker其他方式安装

1.5.1. 修改Docker loglimit。非常重要!

因为docker中的程序syslog,默认会使用emptyDir主机存储,
也就是会在/var/lib/kubernetes/中的产生很多ephemeral-storage内容。
如果不设置,后续会遇到

The node was low on resource: ephemeral-storage. Container xxxx which exceeds its request of xxx

这种问题。

解决办法可以参考这里

vi /etc/docker/daemon.json
设置以下内容,用于限制log的ephemeral-storage大小:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

1.5.2. 修改Docker limit。非常重要!

如果后续要在该集群上安装mongodb,那么必须设置docker limit参数。
如果不设置,mongodb将因为ulimit的问题,导致不断重启
在日志中一般会发现:

Failed to mlock: Cannot allocate locked memory…

配置方法(参考这里):

  1. 执行 systemctl status docker ; systemctl status containerd(arm版本的老docker可能会使用containerd底层)。找到他们的配置文件地址
    假如上述服务的配置地址分别是:/usr/lib/systemd/system/docker.service,/usr/lib/systemd/system/containerd.service
  2. 添加LimitMEMLOCK=infinity

    vi /usr/lib/systemd/system/docker.service

    如果有contaninerd

    vi /usr/lib/systemd/system/containerd.service

    在[Service]一节增加LimitMEMLOCK=infinity

1.5.3. 强制使用overlay2存储引擎

vi /etc/docker/daemon.json
设置以下内容,

{
    "storage-driver": "overlay2",
    "storage-opts": [
        "overlay2.override_kernel_check=true"
    ]
}

1.5.4. 修改docker数据目录(可选)

某些机器,由于/var/lib/docker/目录空间不大,可以考虑迁移该目录到其他地方
比如迁移到 /home下

systemctl stop docker
mkdir -p /home/docker
rsync -avz /var/lib/docker /home/docker (需要安装rsync)
vi /etc/systemd/system/docker.service.d/devicemapper.conf

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd  --graph=/home/docker

将上述内容写入

:wq!

1.5.5. 重启docker

systemctl stop docker

systemctl daemon-reload

如果有containerd,systemctl stop containerd

systemctl daemon-reload

如果有containerd,systemctl start containerd

systemctl start docker

1.6. 节点优化(可选)

  1. 节点内核调优
echo "
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
net.ipv4.conf.all.forwarding=1
net.ipv4.neigh.default.gc_thresh1=4096
net.ipv4.neigh.default.gc_thresh2=6144
net.ipv4.neigh.default.gc_thresh3=8192
net.ipv4.neigh.default.gc_interval=60
net.ipv4.neigh.default.gc_stale_time=120

# 参考 https://github.com/prometheus/node_exporter#disabled-by-default
kernel.perf_event_paranoid=-1

#sysctls for k8s node config
net.ipv4.tcp_slow_start_after_idle=0
net.core.rmem_max=16777216
fs.inotify.max_user_watches=524288
kernel.softlockup_all_cpu_backtrace=1

kernel.softlockup_panic=0

kernel.watchdog_thresh=30
fs.file-max=2097152
fs.inotify.max_user_instances=8192
fs.inotify.max_queued_events=16384
vm.max_map_count=262144
fs.may_detach_mounts=1
net.core.netdev_max_backlog=16384
net.ipv4.tcp_wmem=4096 12582912 16777216
net.core.wmem_max=16777216
net.core.somaxconn=32768
net.ipv4.ip_forward=1
net.ipv4.tcp_max_syn_backlog=8096
net.ipv4.tcp_rmem=4096 12582912 16777216

net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1

kernel.yama.ptrace_scope=0
vm.swappiness=0

# 可以控制core文件的文件名中是否添加pid作为扩展。
kernel.core_uses_pid=1

# Do not accept source routing
net.ipv4.conf.default.accept_source_route=0
net.ipv4.conf.all.accept_source_route=0

# Promote secondary addresses when the primary address is removed
net.ipv4.conf.default.promote_secondaries=1
net.ipv4.conf.all.promote_secondaries=1

# Enable hard and soft link protection
fs.protected_hardlinks=1
fs.protected_symlinks=1

# 源路由验证
# see details in https://help.aliyun.com/knowledge_detail/39428.html
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.all.arp_announce=2

# see details in https://help.aliyun.com/knowledge_detail/41334.html
net.ipv4.tcp_max_tw_buckets=5000
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_synack_retries=2
kernel.sysrq=1



" >> /etc/sysctl.conf

  1. nofile
cat >> /etc/security/limits.conf <
  1. 关闭网卡offload(
    谨慎操作

如果出现【主机上】nodeport访问慢的问题,尝试执行以下内容

特别注意:

1)eth0代表主机网卡,应该按照实际情况修改

2)只有在默认使用flannel网络的情况下执行

ethtool -K eth0 rx off tx off sg off tso off    
ethtool -K flannel.1 rx off tx off sg off tso off 

2. 集群数据库方案

2.1 使用etcd(推荐)

etcd必须3节点起

  1. yum -y install etcd
  2. 参考 这里以及这里 进行配置或二进制下载
  3. 上面地址中,ETCD_INITIAL_CLUSTER_STATE配置exist的地方,应该配置为existing,瓜麻批写错了
  4. vim /etc/etcd/etcd.conf 修改配置
# [member]
#etcd实例名称,每个节点不一样
ETCD_NAME=etcd1
#etcd数据保存目录
ETCD_DATA_DIR="/var/lib/etcd"  
#供外部客户端使用的url
ETCD_LISTEN_CLIENT_URLS="http://本机IP:2379,http://127.0.0.1:2379"
#广播给外部客户端使用的url
ETCD_ADVERTISE_CLIENT_URLS="http://本机IP:2379"


#[cluster]
#集群内部通信使用的URL
ETCD_LISTEN_PEER_URLS="http://本机IP:2380"   
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://本机IP:2380"
#广播给集群内其他成员访问的URL
ETCD_INITIAL_CLUSTER="[ETCD_NAME]=http://本机IP:2380[,[其他节点ETCD_NAME]=http://其他节点IP:2380]"
#初始集群成员列表
#用于指示本次是否为新建集群。有两个取值new和existing。如果填为existing,该
#member启动时会尝试与其他member交互。集群初次建立时,要填为new,经尝试最后
#一个节点填existing也正常,其他节点不能填为existing。集群运行过程中,一个
#member故障后恢复时填为existing,经尝试填为new也正常。全没问题的
ETCD_INITIAL_CLUSTER_STATE="new|existing"
#集群的名称
ETCD_INITIAL_CLUSTER_TOKEN="sobey-arm-etcd-cluster"  
  1. systemctl restart etcd
  2. etcdctl member list检查集群情况
  3. etcdctl cluster-health
    member eabc202e74d53d3 is healthy: got healthy result from http://172.16.149.124:2379
    member b6e44ea4f023b88a is healthy: got healthy result from http://172.16.149.122:2379
    member e50821dfde62301e is healthy: got healthy result from http://172.16.149.123:2379

一些情况:

1.在部署etcd集群时,尝试启动etcd1时,出现报错
Apr 12 01:06:49 k8s-master etcd[3092]: health check for peer 618d69366dd8cee3 could not connect: dial tcp 192.168.81.12:2380: getsockopt: connection refused
Apr 12 01:06:49 k8s-master etcd[3092]: health check for peer acd2ba924953b1ec could not connect: dial tcp 192.168.81.60:2380: getsockopt: connection refused
Apr 12 01:06:48 k8s-master etcd[3092]: publish error: etcdserver: request timed out
分析是因为etcd1的配置文件/etc/etcd/etcd.conf中的ETCD_INITIAL_CLUSTER_STATE是new,而在配置中ETCD_INITIAL_CLUSTER写入了etcd2/3的IP:PORT,这时etcd1尝试去连接etcd2、etcd3,但是etcd2、3的etcd服务此时还未启动,因此需要先启动etcd2和3的etcd服务,再去启动etcd1。
2.在初次部署etcd完成后,尝试执行etcdctl cluster-health命令来查询集群的运行状态,但是报错
cluster may be unhealthy: failed to list members
Error:  client: etcd cluster is unavailable or misconfigured; error #0: dial tcp 127.0.0.1:2379: getsockopt: connection refused
; error #1: dial tcp 127.0.0.1:4001: getsockopt: connection refused
error #0: dial tcp 127.0.0.1:2379: getsockopt: connection refused
error #1: dial tcp 127.0.0.1:4001: getsockopt: connection refused

在etcd配置文件中的ETCD_LISTEN_CLIENT_URLS项,只写入了http://192.168.81.60:2379,而没有写入http://127.0.0.1:2379,加入后即可正常查询。

note:初始集群成员列表 其他机器为existing。或者参考2中所述的方式,用yml一次性启动

2.2 使用mysql双机热备(实验性)

基本目标:使用docker host模式部署在两个server节点上部署mysql。配置参考这里,形成双机主主热备的mysql高可用集群

我们在两个节点,172.16.149.122,172.16.149.123 上先安装各自的mysql,这里我们直接采用docker方式安装

2.2.1 准备工作

  1. docker pull mysql:latest(版本自己考虑,要求5.7以上,比如:docker pull mysql:5.7.32)
    对于ARM机器官方版本只有8.0,docker pull mysql/mysql-server:8.0-aarch64
  2. 先启动一个容器,把/etc/my.cnf拷贝出来备用,这个我们要放到主机上
    docker run -itd --name mysqltest mysql
    mkdir -p /sobey/dbu/mysql
    docker cp mysqltest:/etc/my.cnf /sobey/dbu/mysql/my.cnf
  3. 配置好主机数据目录
    mkdir -p /sobey/dbu/mysql/datas
  4. 删除这个容器
    docker stop mysqltest
    docker rm mysqltest

2.2.2 正式安装

2.2.2.1 修改配置文件

vi /sobey/dbu/mysql/my.cnf。
这里有一个特殊的地放:把目录改为/var/games,主要是为了映射数据到主机。因为/var/games是存在且未用的,否则只有重新编辑镜像,然后创建一个存放data的目录,如果不创建,mysql会报错没有创建目录

每一个主机里面,server-id必须配置不同

datadir=/var/games
socket=/var/lib/mysql/mysql.sock
log-error=/var/games/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
user=mysql

# 配置server-id 每个MySQL实例的server-id都不能相同
server-id=1 # 两个节点的server-id必须不同
# MySQL的日志文件的名字
log-bin=mysql_log_bin
# 作为从库时 更新操作是否写入日志 on:写入  其他数据库以此数据库做主库时才能进行同步
log-slave-updates=on

auto_increment_offset=1 # 设置奇偶自增id,节点1设置为1,节点2设置为2
auto_increment_increment=2  

# MySQL系统库的数据不需要同步 我们这里写了3个  更加保险
# 同步数据时忽略一下数据库 但是必须在使用use db的情况下才会忽略;如果没有使用use db 比如create user  数据还是会同步的
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
replicate-ignore-db=sys
# 使用通配符忽略MySQL系统库的表  这样在create user时也不会进行同步了
replicate_wild_ignore_table=information_schema.%
replicate_wild_ignore_table=mysql.%
replicate_wild_ignore_table=performance_schema.%
replicate_wild_ignore_table=sys.%
# MySQL系统库的日志不计入binlog 这样更加保险了
binlog-ignore-db=information_schema
binlog-ignore-db=mysql
binlog-ignore-db=performance_schema
binlog-ignore-db=sys

上面比较特殊的点:

  • 节点1和节点2的server-id必须不一样
    server-id=1
  • 节点1自增长ID
    auto_increment_offset = 1
    auto_increment_increment = 2 #奇数ID
  • 节点2自增加ID
    auto_increment_offset = 2
    auto_increment_increment = 2 #偶数ID
2.2.2.2 正式启动容器,映射端口、my.cnf、data存放目录.
  1. docker run -itd --name k3smysql -p 3306:3306 -v /sobey/dbu/mysql/my.cnf:/etc/my.cnf -v /sobey/dbu/mysql/datas:/var/games --net=host -e MYSQL_ROOT_PASSWORD=[这里填root密码] mysql
  2. docker ps检查一下安装情况,用客户端连接看看情况
  3. 进入容器,修改root用户允许远程访问
    docker exec -it k3smysql /bin/sh
    mysql -u root -p
    输入root密码,进入后
    修改远程权限,具体查一下5.x和8.0+是不一样的,这里因为是用8.0,所以
    use mysql;
    update user set host=’%’ where user=‘root’;
    flush privileges;
  4. 如果是8.0的数据库,默认使用的是caching_sha2_passsword作为验证plugin,会导致很多客户端报错,有两个办法处理:
  • a) 在my.cnf中设置
    default_authentication_plugin=mysql_native_password
  • b) 按照3的方法进入mysql
    ALTER USER ‘root’@’%’ IDENTIFIED BY ‘root的密码’ PASSWORD EXPIRE NEVER;
    ALTER USER ‘root’@’%’ IDENTIFIED WITH mysql_native_password BY ‘root的密码’;
    FLUSH PRIVILEGES;
    其实只有第二句有意义
2.2.2.3 设置主主

接下来开始配置双机主主模式,这里需要在每个节点上的mysql容器中执行一次不同的操作。其实主主模式就是配置两个主从,先配置(节点1)->(节点2)的主从,然后再反过来配置(节点2)->(节点1)的主从,这样主主的模式就配置好了

2.2.2.3.1 先设置(节点1)->(节点2)的主从

第一步:登录节点1的数据库,并执行如下命令:

  1. 创建用于数据同步的账号 使用mysql_native_password的方式加密,用户名密码根据喜好决定
    CREATE USER ‘replicauser’@’%’ IDENTIFIED WITH mysql_native_password BY ‘replicauser’;
  2. 对replicauser授予备份的权限
    GRANT REPLICATION SLAVE ON *.* TO ‘replicauser’@’%’;
  3. 刷新权限
    FLUSH PRIVILEGES;
  4. 查看MySQL主节点的状态
    SHOW MASTER STATUS;

±------------------±--------±-------------±--------------------------------------------±-----------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
±------------------±--------±-------------±--------------------------------------------±-----------------+
| mysql_master.000001 | 516 | | information_schema,mysql,performance_schema,sys | |
±------------------±--------±-------------±--------------------------------------------±-----------------+
1 row in set

上面得到的File和Position必须记好

第二步:再登录到节点2的数据库,执行如下命令:

#设置节点2的主节点和同步信息
CHANGE MASTER TO MASTER_HOST=‘节点1的ip’,MASTER_PORT=3306,MASTER_USER=‘replicauser也就是上面创建的那个user’,MASTER_PASSWORD=‘replicauser对应的密码’,MASTER_LOG_FILE=‘第一步show master status得到的File’,MASTER_LOG_POS=第一步show master status得到的Postion;
# 开启从库
START SLAVE;

第三步:检查。在节点2上面执行

mysql> SHOW SLAVE STATUS\G;# 查看从库的状态
如果在结果中看到
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
说明OK
===========
如果结果中看到 Slave_IO_Running: No
首先检查网络是否通
其次就是看Last_SQL_Error的信息
如果Last_SQL_Error中有“Could not find first log file name in binary log index file”这种信息
就做如下操作:

  1. 在[节点2]的mysql,执行:stop slave;
  2. 在[节点1]的mysql,执行:
    a)flush logs;
    b) show master status; 也就是第一步中的第4点,重新得到最新的File和Position
  3. 切换回[节点2]的mysql,执行:
    a)CHANGE MASTER TO MASTER_LOG_FILE=‘最新的File’,MASTER_LOG_POS=最新的Position;
    b) start slave;
  4. SHOW SLAVE STATUS\G;# 查看从库的状态
    如果在结果中看到
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes

这样,(节点1)->(节点2)的主从就搭建好了。

2.2.2.3.2 设置(节点2)->(节点1)的主从
  1. 先通过客户端在节点1上执行一个建库建表动作,验证节点1->节点2的同步已经成功
  2. 登录节点2的mysql,执行和节点1第一步相同的命令,创建用户,并且得到File和Position
  3. 切换到节点1上执行前面第二步相同的操作,只是IP换成节点2的,将节点1设置为节点2的从
  4. 在节点1上执行检查动作和处理手段

至此,Mysql双机主主就配置完了。


3. 高可用网络配置

在官方文档上,希望通过一个负载均衡+一个DNS来解决高可用及负载均衡。
负载均衡的目标是接管多个rancher主节点上Traefik Ingress提供的80和443
DNS是解决集群中多个主节点上的负载均衡提供统一入口

因为我们是多机主节点部署方案,并且希望集中式部署所有组件,因此,我们有如下选择:

  1. [DNS]<---->[负载均衡1|80 443,负载均衡2|80 443]<–>[节点1|80 443,节点N|80 443]
  2. [DNS]<---->[(负载均衡1|8880 8443,节点1|80 443),(负载均衡2|8880 443,节点N|80 443)]
  3. [DNS]<---->[节点1|80 443,节点N|80 443]

在一个小型化的集群环境中,选择方案3,并且DNS用keepalived主备安装提供VIP来支持。这样其实就只是让多主节点成为一个多机热备的环境,不必提供负载均衡,目的就是让rancher的server节点高可用而已,而不让rancher server节点负载均衡。如果要负载均衡,采用nginx方案

如果是个中型环境,可以考虑在集群外部nginx做L4负载均衡接管mysql(或etcd)、80、443,同时选择方案1或2。

3.1. 安装nginx(可选)

安装nginx应该是在server节点上服务化安装,但是:由于nginx的 Linux packages,对于arm的支持,都是较高的系统版本,比如centos8、debian10+。不过其docker版本倒是可以很好的无感安装,所以通过docker host网络方式安装nginx

因为rancher需要L4代理,因此nginx的版本要高于1.9才行。https://docs.rancher.cn/docs/rancher2/installation/options/nginx/_index/。 这里有个非常重要的提示:官方安装目标是nginx接管rancher的Traefix提供的80和443,那么就建议nginx单独找机器安装,否则端口冲突。而我们希望集中安装在节点上,那么就要注意,nginx的80转发和443转发,需要修改为8880(或其他)->80,8443(或其他)->443

直接参考hub https://hub.docker.com/_/nginx

docker pull nginx

启动的时候,把配置文件目录给映射到主机上便于后续修改,同时映射一个用于存放日志的地方。然后,在主机上设置一个K3S官方提供的配置文件

  1. mkdir -p /sobey/dbu/nginx/conf.d
  2. mkdir -p /sobey/dbu/nginx/logs
  3. vi /sobey/dbu/nginx/sobey.conf 将内容设置为下面这段配置,注意IP_NODE_1,2…x要修改为正确的server节点IP
user  nginx;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

worker_processes 4;
worker_rlimit_nofile 40000;

events {
    worker_connections 8192;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;
    include /etc/nginx/conf.d/*.conf;
}

stream {
    log_format info '$remote_addr [$time_local] ' '$protocol $status $bytes_sent $bytes_received' '$session_time "$upstream_addr" ' '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
    access_log  /var/log/nginx/stream-access.log  info;
    upstream rancher_servers_http {
        least_conn;
        server :80 max_fails=3 fail_timeout=5s;
        server :80 max_fails=3 fail_timeout=5s;
    }
    server {
        listen 8880;
        proxy_pass rancher_servers_http;
    }

    upstream rancher_servers_https {
        least_conn;
        server :443 max_fails=3 fail_timeout=5s;
        server :443 max_fails=3 fail_timeout=5s;
    }
    server {
        listen     8443;
        proxy_pass rancher_servers_https;
    }
	
	upstream mysql_server {
	
	}
	server {
        listen     3307;
        proxy_pass rancher_servers_https;
    }
}
  1. vi /sobey/dbu/nginx/conf.d/default.conf 设置为下面的内容。因为映射了conf.d目录,所以要设置一个default.conf文件,由于上面用stream方式监听了80,所以http方式的默认端口改为58080(或其他)
server {
    listen  58080;
    listen  [::]:58080;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
  1. docker run --name nginx --net=host -v /sobey/dbu/nginx/conf.d:/etc/nginx/conf.d -v /sobey/dbu/nginx/logs:/var/log/nginx -v /sobey/dbu/nginx/sobey.conf:/etc/nginx/nginx.conf -d nginx

3.2. 安装keepalived

keepalived解决给双机主节点提供VIP,替代DNS的作用
keepalived需要自定义检测脚本来提供切换依据,而检测脚本应该要检测rancher、K3S,但是由于安装K3S需要指定一个外部数据库,因此这里我们先配置并启动keepalived,让他暂时只起到提供VIP的能力。等K3S和Rancher安装完以后,再设置etcd(或Mysql)、K3S和Rancher的检测脚本,然后重启keepalived

开始安装,在每个节点上都安装Keepalived,执行命令如下:

yum -y install keepalived

将配置文件写入

vi /etc/keepalived/keepalived.conf

注意里面的VIP地址要修改为实际的地址

! Configuration File for keepalived

global_defs {
  vrrp_garp_master_refresh 60
  router_id sobeydbuk3s
}

vrrp_script chk_mysql_and_rancher {
  script /sobey/dbu/keep_check.sh
  interval 2
  weight -10
}

vrrp_instance VIP {
  state BACKUP
  interface eth0
  dont_track_primary
  track_interface {
    eth0
  }
  virtual_router_id 39
  garp_master_delay 3
  priority 101 #不同节点填写不同的权重
  preempt_delay 5
  mcast_src_ip 节点本机IP地址
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  track_script {
    chk_mysql_and_rancher
  }
  virtual_ipaddress {
    VIP地址 dev eth0 scope global
  }
}

同时创建一个检测文件备用

vi /sobey/dbu/keep_check.sh

#!/bin/bash

exit 0

chmod +x /sobey/dbu/keep_check.sh

在两个节点启动keepalived

systemctl start keepalived


至此,准备工作做完


4. 安装K3S

安装命令可以使用环境变量的方式进行安装参数设置及3中所述的启动参数设置
这里描述了应该如何使用环境变量

主要参考的是

  1. 使用外部数据库实现高可用安装,这里我们采用是的etcd方案,前面已经安装好了。在启动k3s的时候,要带上外部数据库地址,这里(datastore)有配置说明
  2. 这里(instal-option)给出了在线安装时候,shell脚本可以设置的重要环境变量
  3. 其他额外的需要的启动参数,可以在这里(server-config)看到所有的项

完整在线安装命令就不写了,参考官方即可(注意如果是使用Mysql,其连接信息应该是VIP)。

这里主要讲下载后手动安装

基于脚本的离线安装

  1. 下载k3s安装脚本
    wget https://get.k3s.io > k3s.sh
    或者
    curl -o k3s.sh https://get.k3s.io

  2. 获取二进制文件和镜像文件
    去https://github.com/rancher/k3s/releases下载

    写这篇文章的时候,最新是1.19,但是请下载1.18,因为这里> https://github.com/rancher/k3s/issues/2548有个问题

    1)下载二进制文件拷贝到目标主机的/usr/local/bin中,注意,命名一定要是k3s
    比如这里下载的是k3s-arm64
    wget -O k3s https://github.com/rancher/k3s/releases/download/v1.18.12%2Bk3s1/k3s-arm64
    chmod +x k3s
    cp ./k3s /usr/local/bin/

    2)下载air-gap镜像文件拷贝到/var/lib/rancher/k3s/agent/images/中
    mkdir -p /var/lib/rancher/k3s/agent/images/
    下载tar,比如这里下载的是k3s-airgap-images-arm64.tar
    wget https://github.com/rancher/k3s/releases/download/v1.18.12%2Bk3s1/k3s-airgap-images-arm64.tar
    cp ./k3s-airgap-images-arm64.tar /var/lib/rancher/k3s/agent/images/
    docker load < /var/lib/rancher/k3s/agent/images/k3s-airgap-images-arm64.tar

  3. 添加环境变量并执行安装
    #跳过selinux
    INSTALL_K3S_SELINUX_WARN=true
    #跳过二进制文件下载
    export INSTALL_K3S_SKIP_DOWNLOAD=true
    #设置k3s的二进制文件地址,默认是/usr/local/bin,如果步骤2已经放到这个目录,则可以不用设置
    export INSTALL_K3S_BIN_DIR=2中下载文件所在的目录
    #K3S_DATASTORE_ENDPOINT代表的是外部数据库的连接,这里使用的是etcd的。如果用其他方案,参考官网说明
    export K3S_DATASTORE_ENDPOINT=“http://[etcd1.ip]:2379,http://[etcd2.ip]:2379,http://[etcd3.ip]:2379”
    export INSTALL_K3S_EXEC=“server --docker --kubelet-arg max-pods=200”
    sh k3s.sh

    或者

    INSTALL_K3S_SELINUX_WARN=true INSTALL_K3S_SKIP_DOWNLOAD=true \
    INSTALL_K3S_EXEC=‘server --docker --kubelet-arg max-pods=200’
    K3S_DATASTORE_ENDPOINT=‘http://[etcd1.ip]:2379,http://[etcd2.ip]:2379,http://[etcd3.ip]:2379’ ./k3s.sh

其中:–kubelet-arg=max-pods=200表示,每个节点上最多支持200个POD(Kubernetes默认是110个)
–kubelet-arg的作用是设置kubelet参数,在官网这里有描述。其正确格式可以从这里和这里参考
kubelet参数可以参考K8S的官网

PS: 特别说明:如果启动后需要修改max-pods,参见+9 修改max-pods

这里面特别有几个坑说一下:
1.尽量使用K3S_DATASTORE_ENDPOINT这种方式指定连接参数。如果链接的是mysql数据库,如果参考官网上的内容或其他网络内容,采用启动参数方式指定,会遇到unknown network tcp这种日怪的错误,根本原因是,官网内容中的启动参数中,mysql连接串前后不能用双引号!!!已经提了issue
2.尽量使用1.18版本,因为这里(https://github.com/rancher/k3s/issues/2548)有个错误,我已经遇到了,我在(https://github.com/rancher/k3s/issues/2553)这里提了相同的问题

检查以下安装结果

k3s kubectl get nodes

===========================
NAME STATUS ROLES AGE VERSION
k3s01 Ready master 3m14s v1.18.12+k3s1
k3s02 Ready master 2m17s v1.18.12+k3s1
k3s03 Ready master 2m17s v1.18.12+k3s1

可能出现的问题

如果启动失败,K3S的默认日志在journalctl中,通过journalclt -xe -u k3s可以查看

如果遇到说no default routes found这种问题,参考这里和这里,我们需要设置
1、 可能需要设置ip route
在每个节点上ip route add default via 节点IP
2、 如果还出现了无法启动,且日志中不停出现tls handshake error, 127.0.0.1类似信息
启动参数中加入--flannel-iface <网卡名称> --node-ip 节点IP
样例:
INSTALL_K3S_SELINUX_WARN=true INSTALL_K3S_SKIP_DOWNLOAD=true \
INSTALL_K3S_EXEC=‘server --docker --kubelet-arg max-pods=200 --flannel-iface <网卡名称> --node-ip 节点IP’
K3S_DATASTORE_ENDPOINT=‘http://[etcd1.ip]:2379,http://[etcd2.ip]:2379,http://[etcd3.ip]:2379’ ./k3s.sh

打节点标签(可选)

标签根据实际情况打

k3s kubectl label nodes [节点名(比如k3s01)] env-executor=true env-ficus=true env-java-executor=true env-python-executor=true env-python-ai-executor=true env-java-media-executor=true env-usercenter=true env-schedule=true

一个需要了解的说明

一个k3s server节点,默认情况下也会在当前节点启动agent,也就是既是server也是agent。如果有明确的部署要求,则可以通过–disable-agent,安装一个裸 server


至此,双主节点K3S环境已经准备好


5. 安装并指定私有镜像库

5.1. 安装私有镜像库(可选)

由于我们本身有一个明确的私有镜像库,因此这步对我们的实施来说基本上都可以考虑忽略。
如果是在客户那边需要独立部署一个私有库,那么就找一个机器安装即可。
搜索“docker 安装私有镜像库”或“Harbor”,参考安装

5.2. 配置K3S Server连接到私有镜像库

注意1:我们的私有镜像库是固定了域名images.sobey.com的,因此,这里就直接标出这个域名
注意2:我们的密码也是固定的,但是公有云和私有云有所不同,需提前了解
注意3:我需要提前拿到tls签名文件,以及根证书

在每个K3S Server节点上执行

#拷贝签名文件和根证书
mkdir -p /sobey/dbu/tls
上传私有镜像库签名文件和证书到该目录中
#编辑K3S证书配置信息
vi /etc/rancher/k3s/registries.yaml

mirrors:
  docker.io:
    endpoint:
      - "https://images.sobey.com:5000"# 私有镜像库地址
configs:
  "images.sobey.com:5000":
    auth:
      username: admin # 这是私有镜像仓库的用户名
      password: sobeyhive # 这是私有镜像仓库的密码
    tls:
      cert_file: /sobey/dbu/tls/ficus_crt.crt # 镜像仓库中使用的cert文件的路径。
      key_file: /sobey/dbu/tls/ficus_crt.key # 镜像仓库中使用的key文件的路径。
      ca_file: /sobey/dbu/tls/rootCA.crt   # 镜像仓库中使用的ca文件的路径。

如果是内网环境,并且没有DNS服务,那么需要手动修改hosts
echo -e “xx.xx.xx.xx \t images.sobey.com” | tee -a /etc/hosts

重启k3s
systemctl restart k3s

6. 高可用安装Rancher

我们的目标就是在K3S Server双节点安装基于K3S ENV的高可用Rancker。单机Docker安装不在这里讨论。

选择rancher版本为2.4.10_release。因为这个版本开始,kubernetes1.18作为默认支持,并且修复了一些bug。
4中安装K3S的时候,由于有红色字体的因素,因为我们就选择2.4.10_release作为安装目标。

注意:下面的所有内容,都是基于2.4.10这个特定版本!

在每个K3S Server节点上执行

6.1. 准备rancher 2.4.10 以及相关的docker镜像

在hub上找到正确的镜像,这里以arm64作为样例

docker pull rancher/rancher:v2.4.10-linux-arm64
#因为此时没有设置镜像库,因此设置标签为images.sobey.com/rancher/rancher:v2.4.10 后续helm渲染需要
docker tag rancher/rancher:v2.4.10-linux-arm64 images.sobey.com/rancher/rancher:v2.4.10

由于rancher需要依赖一些其他的软件,也需要安装起来。因此,这里还需要进行这部分镜像的拉取。
具体有哪些,可以从这里,了解到,我们需要准备一些离线镜像。

一种方法是通过rancher-images.txt找到所需要软件镜像列表,然后在hub上找到这些镜像的正确版本,依次pull下来。

当然,在一般环境中,可以不太关心每一个镜像的实际情况,也可以通过官方给出的方式直接处理

#根据上面的地址,到官方下载对应的脚本和数据文件。也可以到国内镜像下

  1. rancher-images.txt
  2. rancher-load-images.sh
  3. rancher-save-images.sh

#拷贝上述文件到目标机器同一目录下
mkdir -p /sobey/rancher_install
cd /sobey/rancher_install
#拷贝进这个目录
curl -O https://github.com/rancher/rancher/releases/download/v2.4.10/rancher-images.txt
curl -O https://github.com/rancher/rancher/releases/download/v2.4.10/rancher-load-images.sh
curl -O https://github.com/rancher/rancher/releases/download/v2.4.10/rancher-save-images.sh
#按照 这里2、收集 cert-manager 镜像所描述的方式执行
#去重
sort -u rancher-images.txt -o rancher-images.txt
#添加镜像拉取
chmod +x rancher-save-images.sh
./rancher-save-images.sh --image-list ./rancher-images.txt
#完成时,当前目录会输出名为rancher-images.tar.gz的压缩包
#同时,这些镜像已经save到本地镜像列表中,可以通过docker images查看


特别的:
如果是私有库,可以通过脚本将镜像推送到私有库
chmod +x rancher-load-images.sh
./rancher-load-images.sh --image-list ./rancher-images.txt --registry 私库地址

特别注意1:
在镜像拉取过程中,一定要注意控制台日志,其中Image pull failed的需要记录下来
有可能是没有官方的平台版本,比入arm64。也可能其他原因导致的失败
针对这些failed的,要手动拉取 docker pull xxxxxx
如果是因为平台不对,那么可以去hub.docker.com中,查询民间的镜像,拉取后手动修改标签

情况一:官方压根儿没有相应的版本
这里以arm64上面rancher/configmap-reload:v0.3.0-rancher2为例
在arm64上面,会看到Image pull failed: rancher/configmap-reload:v0.3.0-rancher2
于是执行:docker pull rancher/configmap-reload:v0.3.0-rancher2
结果发现没有此镜像,原因是它没有官方的arm64版本,因此去hub.docker.com中查询configmap-reload
结果发现比较流行的jimmidyson/configmap-reload
于是执行:docker pull jimmidyson/configmap-reload:v0.3.0
完成后,打标签:docker tag jimmidyson/configmap-reload:v0.3.0 rancher/configmap-reload:v0.3.0-rancher2

情况二:官方有较近版本
1、rancher/coredns-coredns:1.6.2
我们发现官方上,1.6.3就支持了arm64,这种代差非常小,从官方issue里面可知差别不大
于是执行:docker pull rancher/coredns-coredns:1.6.3
docker tag rancher/coredns-coredns:1.6.3 rancher/coredns-coredns:1.6.2

情况三:有一些确实搞不定的,可能只有靠手动build了
截至此时,2.4.10中,arm64上面无法pull的有
rancher/fluentd:v0.1.19,rancher/istio-coredns-plugin:0.2-istio-1.1, rancher/istio-kubectl:1.5.10,rancher/kubernetes-external-dns:v0.7.3,rancher/thanosio-thanos:v0.15.0
但是目测这些都是和istio有关,而目前我们还不会大规模使用istio,因此可以暂时忽略

特别注意2:
上述镜像,应该同时推送到私有库,以备后续的Agent节点使用
或者,export出来,拷贝到Agent节点上
最笨的,将这个Faild List拷贝出来,在Agent上按红色的说明执行一次

特别注意3:

如果【没有推送到私有镜像库】,那么,我们应该对【需要的镜像】进行docker tag处理。
比如docker tag rancher/rancher:v2.4.10-linux-arm64 images.sobey.com/rancher/rancher:v2.4.10 因为没有私库,只有做一次相当于人工pull的操作。
——需要的镜像,意思是rancher本身,或者rancher运行起来之后,界面上提示无法pull的镜像





下面后续的操作,其实可以只在一台节点上操作。当然,也可以根据实际情况,每个节点都操作一次。


6.2. 准备Rancher Server证书

6.2.1. 从DBU人员手中获取证书

从DBU人员手中获取到Rancher访问需要的证书(和5.2中的是两个不同的证书),默认情况下会得到名为“dbu_rancher_crt”的证书,默认我们设置的DNS为dburancher.sobey.com

#拷贝签名文件和根证书
mkdir -p /sobey/dbu/tls/rancher
上传签名文件和证书到该目录中

6.2.2. 自建证书

  1. 拷贝下面的内容到 /root/mktls.sh
#!/bin/bash -e

help ()
{
    echo  ' ================================================================ '
    echo  ' --ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;'
    echo  ' --ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;'
    echo  ' --ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(SSL_TRUSTED_DOMAIN),多个扩展域名用逗号隔开;'
    echo  ' --ssl-size: ssl加密位数,默认2048;'
    echo  ' --ssl-cn: 国家代码(2个字母的代号),默认CN;'
	echo  ' --ssl-date: 有效天数;'
    echo  ' 使用示例:'
    echo  ' ./create_self-signed-cert.sh --ssl-domain=www.test.com --ssl-trusted-domain=www.test2.com \ '
    echo  ' --ssl-trusted-ip=1.1.1.1,2.2.2.2,3.3.3.3 --ssl-size=2048 --ssl-date=3650'
    echo  ' ================================================================'
}

case "$1" in
    -h|--help) help; exit;;
esac

if [[ $1 == '' ]];then
    help;
    exit;
fi

CMDOPTS="$*"
for OPTS in $CMDOPTS;
do
    key=$(echo ${OPTS} | awk -F"=" '{print $1}' )
    value=$(echo ${OPTS} | awk -F"=" '{print $2}' )
    case "$key" in
        --ssl-domain) SSL_DOMAIN=$value ;;
        --ssl-trusted-ip) SSL_TRUSTED_IP=$value ;;
        --ssl-trusted-domain) SSL_TRUSTED_DOMAIN=$value ;;
        --ssl-size) SSL_SIZE=$value ;;
        --ssl-date) SSL_DATE=$value ;;
        --ca-date) CA_DATE=$value ;;
        --ssl-cn) CN=$value ;;
    esac
done

# CA相关配置
CA_DATE=${CA_DATE:-3650}
CA_KEY=${CA_KEY:-cakey.pem}
CA_CERT=${CA_CERT:-cacerts.pem}
CA_DOMAIN=cattle-ca

# ssl相关配置
SSL_CONFIG=${SSL_CONFIG:-$PWD/openssl.cnf}
SSL_DOMAIN=${SSL_DOMAIN:-'www.rancher.local'}
SSL_DATE=${SSL_DATE:-3650}
SSL_SIZE=${SSL_SIZE:-2048}

## 国家代码(2个字母的代号),默认CN;
CN=${CN:-CN}

SSL_KEY=$SSL_DOMAIN.key
SSL_CSR=$SSL_DOMAIN.csr
SSL_CERT=$SSL_DOMAIN.crt

echo -e "\033[32m ---------------------------- \033[0m"
echo -e "\033[32m       | 生成 SSL Cert |       \033[0m"
echo -e "\033[32m ---------------------------- \033[0m"

if [[ -e ./${CA_KEY} ]]; then
    echo -e "\033[32m ====> 1. 发现已存在CA私钥,备份"${CA_KEY}"为"${CA_KEY}"-bak,然后重新创建 \033[0m"
    mv ${CA_KEY} "${CA_KEY}"-bak
    openssl genrsa -out ${CA_KEY} ${SSL_SIZE}
else
    echo -e "\033[32m ====> 1. 生成新的CA私钥 ${CA_KEY} \033[0m"
    openssl genrsa -out ${CA_KEY} ${SSL_SIZE}
fi

if [[ -e ./${CA_CERT} ]]; then
    echo -e "\033[32m ====> 2. 发现已存在CA证书,先备份"${CA_CERT}"为"${CA_CERT}"-bak,然后重新创建 \033[0m"
    mv ${CA_CERT} "${CA_CERT}"-bak
    openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}"
else
    echo -e "\033[32m ====> 2. 生成新的CA证书 ${CA_CERT} \033[0m"
    openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} -days ${CA_DATE} -out ${CA_CERT} -subj "/C=${CN}/CN=${CA_DOMAIN}"
fi

echo -e "\033[32m ====> 3. 生成Openssl配置文件 ${SSL_CONFIG} \033[0m"
cat > ${SSL_CONFIG} <<-EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
EOF

if [[ -n ${SSL_TRUSTED_IP} || -n ${SSL_TRUSTED_DOMAIN} ]]; then
    cat >> ${SSL_CONFIG} <<-EOF
subjectAltName = @alt_names
[alt_names]
EOF
    IFS=","
    dns=(${SSL_TRUSTED_DOMAIN})
    dns+=(${SSL_DOMAIN})
    for i in "${!dns[@]}"; do
      echo DNS.$((i+1)) = ${dns[$i]} >> ${SSL_CONFIG}
    done

    if [[ -n ${SSL_TRUSTED_IP} ]]; then
        ip=(${SSL_TRUSTED_IP})
        for i in "${!ip[@]}"; do
          echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG}
        done
    fi
fi

echo -e "\033[32m ====> 4. 生成服务SSL KEY ${SSL_KEY} \033[0m"
openssl genrsa -out ${SSL_KEY} ${SSL_SIZE}

echo -e "\033[32m ====> 5. 生成服务SSL CSR ${SSL_CSR} \033[0m"
openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} -subj "/C=${CN}/CN=${SSL_DOMAIN}" -config ${SSL_CONFIG}

echo -e "\033[32m ====> 6. 生成服务SSL CERT ${SSL_CERT} \033[0m"
openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} -days ${SSL_DATE} -extensions v3_req -extfile ${SSL_CONFIG}

echo -e "\033[32m ====> 7. 证书制作完成 \033[0m"
echo
echo -e "\033[32m ====> 8. 以YAML格式输出结果 \033[0m"
echo "----------------------------------------------------------"
echo "ca_key: |"
cat $CA_KEY | sed 's/^/  /'
echo
echo "ca_cert: |"
cat $CA_CERT | sed 's/^/  /'
echo
echo "ssl_key: |"
cat $SSL_KEY | sed 's/^/  /'
echo
echo "ssl_csr: |"
cat $SSL_CSR | sed 's/^/  /'
echo
echo "ssl_cert: |"
cat $SSL_CERT | sed 's/^/  /'
echo

echo -e "\033[32m ====> 9. 附加CA证书到Cert文件 \033[0m"
cat ${CA_CERT} >> ${SSL_CERT}
echo "ssl_cert: |"
cat $SSL_CERT | sed 's/^/  /'
echo

echo -e "\033[32m ====> 10. 重命名服务证书 \033[0m"
echo "cp ${SSL_DOMAIN}.key tls.key"
cp ${SSL_DOMAIN}.key tls.key
echo "cp ${SSL_DOMAIN}.crt tls.crt"
cp ${SSL_DOMAIN}.crt tls.crt
  1. 使用参数执行上述脚本

–ssl-domain: 生成ssl证书需要的主域名,如不指定则默认为www.rancher.local,如果是ip访问服务,则可忽略;
–ssl-trusted-ip: 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,多个IP用逗号隔开;
–ssl-trusted-domain: 如果想多个域名访问,则添加扩展域名(TRUSTED_DOMAIN),多个TRUSTED_DOMAIN用逗号隔开;至少有一个和ssl-domain一样
–ssl-size: ssl加密位数,默认2048;
–ssl-cn: 国家代码(2个字母的代号),默认CN;

–ssl-date: 有效天数;

#使用示例:

./mktls.sh --ssl-domain=dburancher.sobey.com --ssl-trusted-domain=dburancher.sobey.com --ssl-trusted-ip=172.16.149.139,172.16.149.122,172.16.149.123,172.16.149.124 --ssl-size=2048 --ssl-date=3650

  1. 查看结果

ls -l
#可以看到
cacerts.pem #根证书,部署rancher会使用
cacerts.srl
cakey.pem
mktls.sh
openssl.cnf
tls.crt #证书,部署rancher渲染会使用
tls.key #证书密钥,部署rancher渲染会使用
uosrancher.test.com.crt #和tls.crt 是一个东西
uosrancher.test.com.csr
uosrancher.test.com.key #和tls.key 是一个东西

6.2.2.1. 将Charts仓库和镜像仓库的根证书加入到自建根证书(可选)

在使用自建rancher证书的情况下,如果Charts仓库和镜像仓库使用了其他证书,并且其他证书是从其他根证书签发,以harbor.sobey.com的证书为例,其签发根证书为rootCA.pem

那么,需要将rootCA.pem的内容加入到当前生成的根证书中

  1. 从渠道拿到rootCA.pem
  2. cat rootCA.pem | tee -a /sobey/dbu/tls/rancher/cacerts.pem

或者,用官网的说明,由于rancher要访问自定义的仓库或商店,那么需要按此附加授信CA

  1. 在6.3.2的2渲染charts中,增加参数 --set additionalTrustedCAs=true
  2. 从渠道拿到rootCA.pem(可能有多个),将其复制到一个名为ca-additional.pem的文件中
    cat rootCA.pem | tee -a ca-additional.pem(如果还有多个,则依次创建)
    然后在k3s中创建ca-additional密文
    kubectl -n cattle-system create secret generic tls-ca-additional --from-file=ca-additional.pem=./ca-additional.pem

6.2.3. 使用已经签发好的证书(可选)

如果用户自己具备证书,那么可以使用用户提供的证书

只需要拷贝用户的证书文件和证书key文件即可。但是,需要注意:

  1. 证书文件必须是PEM格式
  2. 证书key文件必须是PKCS1格式

具体可以参考这里来处理

6.3. 准备Helm和rancher 2.4.10 charts

Helm 是安装 Rancher 高可用集群时会用到的工具。
Helm 是 Kubernetes 的软件包管理工具。Helm chart 为 Kubernetes YAML manifest 文件提供了模板语法。通过 Helm,可以创建可配置的 Deployment YAML,而不是只能用静态的 YAML。

6.3.1. 下载Helm

在每个server节点上执行

由于rancher官方推荐使用3.0以上的helm,因此在helm 3.4.0下载一个合适的版本

使用wget或curl下载对应的版本
tar -zxvf helm-v3.4.0-linux-$ARCH.tar.gz -C $target_dir
在解压目中找到helm程序,移动到需要的目录中
mv t a r g e t d i r / h e l m / u s r / l o c a l / b i n / h e l m < b r > ∗ 注 意 上 面 的 target_dir/helm /usr/local/bin/helm
*注意上面的
targetdir/helm/usr/local/bin/helm<br>
符号对应的都是要按实际情况修改的*

6.3.2. 拉取rancher charts

  1. 在节点外的机器上拉取rancher charts

这里我们没有创建和注册charts repo,也没有像官网所述去regsitry一个rancher的charts repo,而是直接通过URL拉取一个完整的rancher-charts到本地后使用

  1. 在任意一个可以上网的环境中,安装helm
  2. helm repo add rancher-stable https://releases.rancher.com/server-charts/stable
  3. helm pull rancher-stable/rancher --version 2.4.10
  4. 将上述下载好的2.4.10 rancher charts tar文件,拷贝到在6.1拉取镜像的时候创建好的/sobey/rancher_install中
    cp xxxx.tar.gz /sobey/rancher_install/
  1. 然后开始渲染charts
    进入对应的目录,执行helm命令

cd /sobey/rancher_install
#按照官方说明,渲染charts模板
helm template rancher ./rancher-.tgz --output-dir . \
–namespace cattle-system \
–set hostname=
–set rancherImage= \
–set rancherImageTag= \
–set ingress.tls.source=secret \
#【注意】,如果是使用已经签发的证书,这里【不设置】privateCA
–set privateCA=true \
#这个参数特别说明一下,如果是测试环境,可以考虑不设置。但是生产环境还是应该设置好。其作用
#就是设置rancher的system-default-registry。
#按理说生产环境的镜像库,应该包含所有需要的镜像,rancher管理的k3s默认会从镜像库地址拉取镜像,除非本地有对应的镜像
#如果不设置,那么就是从hub.docker.com拉取,除非本地有对应的镜像
–set systemDefaultRegistry=
–set useBundledSystemChart=true

PS: set参数的时候,提醒一下,注意6.2.2.1. 中的内容

占位符 描述
Rancher 版本,这里是2.4.10
官方叫负载均衡器对应的 DNS,也就是6.2中rancher集群证书的域名,默认是dburancher.sobey.com
私有镜像库对应的 DNS,参见5.2,我们默认是images.sobey.com:5000
Rancher镜像名,官方给出的是/rancher/rancher,因为它是从私有镜像库拉取,而我们因为在6.1中已经导入了rancher镜像,同时我们也没有在6.1中执行这里要求的推送镜像到私库,因此这里直接写导入到本地的镜像
Rancher镜像版本,这里是v2.4.10。在6.1中设置了这个tag。当然,也可以不设置,直接指定为实际的tag

一个完整的样例:helm template rancher ./rancher-2.4.10.tgz --output-dir . --namespace cattle-system --set hostname=dburancher.sobey.com --set rancherImage=rancher/rancher --set rancherImageTag=v2.4.10 --set ingress.tls.source=secret --set privateCA=true --set systemDefaultRegistry=images.sobey.com --set useBundledSystemChart=true

完成以后,在当前目录应该看到一个rancher目录,里面有生成的templates/各种yaml

6.4. 正式安装rancher

6.4.1. 在K3S中创建rancher的命名空间

在任意一个server节点中执行

k3s kubectl create namespace cattle-system

6.4.2. 设置rancher server的证书

参考官方说明,设置6.2中准备好的证书

在任意一个server节点中执行

#设置证书
k3s kubectl -n cattle-system create secret tls tls-rancher-ingress --cert=/sobey/dbu/tls/rancher/dbu_rancher_crt.crt --key=/sobey/dbu/tls/rancher/dbu_rancher_crt.key
#设置根证书
cp /sobey/dbu/tls/rancher/rootCA.crt /sobey/dbu/tls/rancher/rootCA.pem
k3s kubectl -n cattle-system create secret generic tls-ca --from-file=cacerts.pem=/sobey/dbu/tls/rancher/rootCA.pem

6.4.3 最后一步,安装rancher

进入6.1创建的/sobey/rancher_install目录
此目录在6.3.2还拉取了charts,并且生成了最终的包含所有yaml的rancher目录

在任意一个节点上操作

cd /sobey/rancher_install
k3s kubectl -n cattle-system apply -R -f ./rancher

最后的检查

k3s kubectl -n cattle-system rollout status deploy/rancher
#应该显示如下信息
Waiting for deployment “rancher” rollout to finish: 0 of 3 updated replicas are available…
Waiting for deployment “rancher” rollout to finish: 1 of 3 updated replicas are available…
Waiting for deployment spec update to be observed…
Waiting for deployment “rancher” rollout to finish: 1 of 3 updated replicas are available…
Waiting for deployment “rancher” rollout to finish: 2 of 3 updated replicas are available…
deployment “rancher” successfully rolled out

k3s kubectl get pods --namespace=cattle-system
#应该看到类似的信息
NAME                 READY   STATUS RESTARTS AGE
rancher-7d688cbccb-9cldj   1/1     Running   1       5m54s
rancher-7d688cbccb-5jlcb   1/1     Running   0       5m54s
rancher-7d688cbccb-5zcmt  1/1     Running   0       5m54s

6.4.4. 验证

打开浏览器,设置hosts指向 dburancher.sobey.com(这是6.2证书的域名),访问rancher界面

如果要达成通过IP直接访问rancher,那么此时请不要配置任何rancher界面上的内容,直接看下面6.5

6.5. 配置通过IP直接访问多节点rancher(可选)

某些情况下,我们希望可以通过IP(比如VIP)直接访问rancher,而不需要配置域名。

我们可以通过配置L4负载均衡的方式来达成
在+7这一章节,我们可以知道,K3S通过L4负载均衡(svclb)可以直接开放引导主机流量到集群中
因此,如果需要直接通过IP访问,我们可以创建一个L4负载均衡

apiVersion: v1
kind: Service
metadata:
  annotations:
    field.cattle.io/targetDnsRecordIds: '["cattle-system:rancher"]'
  labels:
    cattle.io/creator: rancheripl4
  name: traefik-ip-entrypoint-l4
  namespace: cattle-system
spec:
  externalTrafficPolicy: Cluster
  ports:
  - name: http
    port: 30080
    protocol: TCP
    targetPort: 80
  - name: https
    port: 30443
    protocol: TCP
    targetPort: 443
  sessionAffinity: None
  type: LoadBalancer

拷贝以上内容,到某个主机的目录中,比如 ~/service-rancher-ip.yaml
注意,其中可能会修改的地方,是port字段。它表示通过IP的哪个端口来访问rancher

然后,在该主机上执行:

k3s kubectl apply -f ~/service-rancher-ip.yaml

如果正常,k3s会创建一个l4负载均衡,并且将主机的30080和30443引导到rancher的集群服务上。

6.5.1. 验证

打开浏览器,输入 http://${VIP}:30080 ,访问rancher界面

7. 设置keepalived检测脚本

在3.2中,安装keepavlived,预留了一个keep_check.sh脚本。
这里我们需要设置这个检查脚本,用于keepalived的检测切换,何海强给了我们一段脚本

在每台server节点上执行(或scp拷贝)

vi /sobey/dbu/keep_check.sh

#!/bin/bash

KA_CHECK=$(ps -A -o pid,cmd|grep "keep_check.sh"|grep -v $$|grep -v grep|wc -l)
if [ "$KA_CHECK" -gt "1" ]; then
    exit 0
fi

bin=$(cd $(dirname $0); pwd)
LOG_FILE="$bin/ka_check.log"
CONTAINER_NAME="k3smysql"

MYSQL_HEALTH_STATUS=$(docker inspect --format '{{.State.Health.Status}}' $CONTAINER_NAME)
if [ "$MYSQL_HEALTH_STATUS" = "healthy" ]; then
    K3S_HEALTH_STATUS=$(systemctl is-active k3s)
    if [ "$K3S_HEALTH_STATUS" = "active" ]; then
        COMPONENT_HEALTH_STATUS=$(kubectl get cs|awk '/Healthy/{print $2}'|wc -l)
        if [ "$COMPONENT_HEALTH_STATUS" != "2" ]; then 
            echo "$(date):
            $(kubectl get cs)" >>$LOG_FILE
            exit 1
        fi
    else
        echo "$(date):  K3S_HEALTH_STATUS = $K3S_HEALTH_STATUS" >>$LOG_FILE
        exit 1
    fi
else
    echo "$(date):  MYSQL_HEALTH_STATUS = $MYSQL_HEALTH_STATUS" >>$LOG_FILE
    exit 1
fi

8. cattle-cluster-agent和cattle-node-agent几乎一定会处理的问题

8.1. 域名解析问题

我们看到cattle-cluster-agent和cattle-node-agent工作负载不能正常启动
从日志上看到,ERROR: https://xxxx/ping is not accessible (Could not resolve host: rancher.my.org)

或者,我们看到某些配置的域名无法访问,比如应用商店里面配置了一个harbor.sobey.com,无法连接,这些都是域名解析导致。

一般来说是这个地方导致的问题可以参照解决。
或者,点击工作负载的“编辑”—>“显示高级选项”–>“网络”—>手动设置hosts映射,将dburancher.sobey.com正确的映射到VIP地址上

但是,最好的一个办法是:

1、打开rancher,找到System下面的coredns工作负载。
2、可以看到coredns工作负载关联了一个coredns配置映射(config-map)。或者直接从“资源”–>“配置映射”中找到它
3、修改这个coredns的配置映射中的NodeHosts配置项,类似hosts文件一样修改它即可

这样,整个集群内,都可以通过此coredns进行域名解析

8.2. Ingress导致的证书解析错误

Traefik Ingress导致的证书问题

经过1的处理,在日志中看到
Issuer of last certificate found in chain does not match with CA certificate Issuer......
cattle-cluster-agent Server certificate is not valid......
并且日志堆栈中显示了一个压根儿没见过的CA信息

原因是因为默认开启了Traefik(安装的时候没有–disable Traefik)——在命名空间kube-system工作负载列表中可以看到部署了Traefik。

Traefik默认接管了K3S的L4入口,官网这里进行了说明,这里在介绍集群外部负载均衡入口配置的时候也说明了,因此,集群内部会通过此入口进行80和443的流量处理。

根据其yaml可以看到,它关联了一个名为 traefik-default-cert的SSL配置

      - configMap:
          defaultMode: 420
          name: traefik
        name: config
      - name: ssl
        secret:
          defaultMode: 420
          secretName: traefik-default-cert
status:

正因为这个SSL配置的证书信息并没有指定为我们自己的证书,而内部的通讯走的是集群内部的80和443,也就是经过Traefik,因此提示了证书问题导致无法启动。

处理方法:

#删除现有的 traefik-default-cert
k3s kubectl -n kube-system delete secret traefik-default-cert
#重新关联证书(这里的证书是6.2准备的)
k3s kubectl -n kube-system create secret generic traefik-default-cert --from-file=tls.crt=/sobey/dbu/tls/rancher/dbu_rancher_crt.crt --from-file=tls.key=/sobey/dbu/tls/rancher/dbu_rancher_crt.key


或者,手动拷贝crt和key的内容,在rancher中点击“资源”—>“密文”,找到traefik-default-cert进行修改

完成以后,在工作负载中重新部署Traefikcatlle-cluster-agentcattle-node-agent

8.3. 某些CA证书无法验证,报X509错误

某些情况下,比如public证书过期了,甚至于,我们就想用自己的自签名证书

会看到容器中报错类似:X509: unknown autority zzzzzz

处理办法:

CA证书内容(注意,是CA证书,也就是根证书),拷贝到/etc/kubernetes/ssl/certs/serverca文件中
编辑cattle-cluster-agent,参考cattle-node-agent数据卷:k8s-ssl手动配置数据卷

这样即可解决SSL证书验证问题


结束

至此,基于Mysql主主的双节点高可用K3S+Rancher集群就部署完成了


+1:完全离线安装

上面的整个过程,多少都利用了在线处理。
如果要完整的离线安装,主要是通过这几个点来达成:

  1. 但凡需要yum install的地方

    【联网机】---->yum install---->【rpm包】---->copy---->【不能联网机】---->yum localinstall

    以nginx举例,创建一个你喜欢的目录,我这里是
    mkdir -p /usr/local/rpms/nginx
    下载包
    yum install --downloadonly --downloaddir=/usr/local/rpms/nginx nginx
    将下载的包拷贝到目标机/usr/local/rpms/nginx/
    yum localinstall /usr/local/rpms/nginx/*.rpm

  2. 但凡需要docker pull的地方
    方法一)和上面相似,先到一个联网机"docker pull需要的镜像",然后"docker export这个镜像",拷贝镜像到目标机,在目标机上执行"docker load < 镜像"
    方法二)利用一个私有,可访问的Harbor作为镜像库

  3. 但凡是wget或curl下载的,在联网机下载好以后拷贝即可

+1.1. 已经准备好的离线包(以标准centos为例,UOS特殊处理)

可以从DBU开发人员那里拿到离线包,离线包包含如下内容:

/1.yum-utils/2.docker/3.etcd/4.k3s/5.rancher

安装方式

  1. yum localinstal -y /1.yum-utils/*.rpm
  2. yum localinstal -y /2.docker/*.rpm
  3. yum localinstal -y /3.etcd/*.rpm,参考2.1 安装etcd进行etcd安装
  4. 使用/4.k3s目录中的内容,参考4. 安装K3S进行k3s的安装
  5. 使用/5.rancher目录中的内容,参考6. 高可用安装rancher进行rancher的安装。
    5.1. 其中helm相关内容在/5.rancher/helm中
    5.2. 另外注意,由于离线包中已经存在rancher-images.tar.gz,因此,只需要docker load即可

+2:在K3S集群加入一个Agent节点

由于我们是采用的

创建双主机K3S-->K3S部署rancher

这种方式构建的部署方案,按照官方的说法,这仅仅是“高可用部署rancher”而已。也就是说,相当于我们为了部署一个高可用的rancher,所以部署了一个K3S而已。
按照官方建议,应该是用这个高可用的rancher,重新去创建一个新的集群来作为运行时集群
相当于

(Rancher【on K3S】)---->manage—>(new Cluster)

然而,我们在我们面对的一般项目中,更希望一体化运行,也就是

(Rancher【K3S】)-------
            ^       |
            |_______

因此,我们目前需要手动的添加Agent节点到集群中

+2.1. 节点环境准备

准备一个节点,然后安装必须的东西

  1. 执行本文“1. 准备工作”中的所有内容
  2. 写入VIP域名解析

echo -e “xxxx.xxx.xx.xx \t dburancher.sobey.com” | tee -a /etc/hosts

  1. 将本文“4. 安装K3S”中在server节点上放置的的k3s.shK3Sk3s-airgap-images-$ARCH.tar文件拷贝过来(因为我们一般在root目录下操作,所以先放到这里面)

scp [email protected]:/root/* /root/

  1. 将文件放置到目标位置,并做比较要的步骤处理

cp /root/k3s /usr/local/bin/
chmod +x /usr/local/bin/k3s
mkdir -p /var/lib/rancher/k3s/agent/images/
cp ./k3s-airgap-images- A R C H . t a r / v a r / l i b / r a n c h e r / k 3 s / a g e n t / i m a g e s / d o c k e r l o a d < / v a r / l i b / r a n c h e r / k 3 s / a g e n t / i m a g e s / k 3 s − a i r g a p − i m a g e s − ARCH.tar /var/lib/rancher/k3s/agent/images/ docker load < /var/lib/rancher/k3s/agent/images/k3s-airgap-images- ARCH.tar/var/lib/rancher/k3s/agent/images/dockerload</var/lib/rancher/k3s/agent/images/k3sairgapimagesARCH.tar
yum install -y container-selinux selinux-policy-base(可选,如果安装报相应的错误,就按此处理)
yum install -y https://rpm.rancher.io/k3s/stable/common/centos/7/noarch/k3s-selinux-0.2-1.el7_8.noarch.rpm(可选,如果安装报相应的错误,就按此处理)

5(可选). load必要的镜像

如果6.1中推送了私库,那么本操作跳过。
如果在本文“6.1”中,没有推送镜像到私库,那么,将server节点上准备好的/sobey/rancher_install/rancher-images.tar.gz拷贝过来,然后load。

mkdir -p /sobey/rancher_install/
scp [email protected]:/sobey/rancher_install/rancher-images.tar.gz /sobey/rancher_install/rancher-images.tar.gz
docker load < /sobey/rancher_install/rancher-images.tar.gz
#针对6.1红色字体部分,如果没有上传相应的镜像到私有库,那么就只有拷贝,如果没有拷贝,那么就获取Failed List按红色字体说明执行一次

  1. 按照本文“5.2”的步骤,配置镜像库

#拷贝签名文件和根证书
mkdir -p /sobey/dbu/tls
scp [email protected]:/sobey/dbu/tls/* /sobey/dbu/tls/
#编辑K3S证书配置信息
mkdir -p /etc/rancher/k3s
vi /etc/rancher/k3s/registries.yaml

mirrors: 
  docker.io: 
    endpoint: 
      - "https://images.sobey.com:5000"# 私有镜像库地址 
configs: 
  "images.sobey.com:5000": 
    auth: 
      username: admin # 这是私有镜像仓库的用户名 
      password: sobeyhive # 这是私有镜像仓库的密码 
    tls: 
      cert_file: /sobey/dbu/tls/ficus_crt.crt # 镜像仓库中使用的cert文件的路径。 
      key_file: /sobey/dbu/tls/ficus_crt.key # 镜像仓库中使用的key文件的路径。 
      ca_file: /sobey/dbu/tls/rootCA.crt   # 镜像仓库中使用的ca文件的路径
  1. 如果是内网环境,并且没有DNS服务,那么需要手动修改hosts

echo -e “xx.xx.xx.xx \t images.sobey.com” | tee -a /etc/hosts

+2.2. 启动Agent节点

  1. 获取token

参考官网说明,获取token

scp [email protected]:/var/lib/rancher/k3s/server/node-token /root/k3s_server_token

  1. 启动Agent

cd root
INSTALL_K3S_SKIP_DOWNLOAD=true K3S_TOKEN_FILE=’/root/k3s_server_token’ K3S_URL=‘https://dburancher.sobey.com:6443’ INSTALL_K3S_EXEC=‘agent --docker --kubelet-arg=max-pods=200’./k3s.sh

其中–kubelet-arg=max-pods=200参考:4. 安装K3S 这一节的说明

  1. 打节点标签(可选)

标签根据实际情况打不同的标签

k3s kubectl label nodes [节点名] env-executor=true env-java-executor=true env-python-executor=true env-python-ai-executor=true env-java-media-executor=true

+3. 更换rancher的默认镜像库地址

在某些情况下,可能会更换rancher的镜像库地址。

  1. 修改每个主机的hosts文件,IP指向正确的镜像库域名
  2. 在rancher中找到rancher的工作负载,“编辑”–>“修改环境变量”,将CATTLE_SYSTEM_DEFAULT_REGISTRY修改为正确的镜像库域名(或者删除——参见6.3.2helm命令部分的说明)

+4. 删除rancher

某些情况下可能会删除rancher,操作方式

1、根据这里的说明,下载对应的system-tools
2、在某个机器上操作
如果这个机器是server节点以外的机器,则先拷贝节点的/etc/rancher/k3s/k3s.yaml到准备好的路径

./system-tools remove --kubeconfig

其中KUBECONFIG就是/etc/rancher/k3s/k3s.yaml拷贝后的路径

3、彻底清除kubernetes的namespace

2执行以后,通过 k3s kubectl get namespaces,看到对应的namespace还是Terminating状态
此时,在server节点上执行

KUBE_EDITOR=“vi” kubectl edit namespaces

其中 是需要删除的 namespace

找到

finalizers:
  - controller.cattle.io/namespace-auth

将其改为

finalizers: []

保存即可,此时将删除namespace

如果上述处理删除不掉,则通过终极大法:

  1. k3s kubectl get namespace -o json > tmp.json
  2. vi tmp.json,删除任何"finalizers"里面的"kubernetes"
    #开启一个代理终端,主要是避免环境变量问题
  3. k3s kubectl proxy
    #应该会看到Starting to serve on 127.0.0.1:8001
  4. 打开另一个ssh终端
    #在新打开的终端执行
  5. curl -k -H “Content-Type: application/json” -X PUT --data-binary @tmp.json http://127.0.0.1:8001/api/v1/namespaces/annoying-namespace-to-delete/finalize

+5. 修改ETCD节点信息

某些情况下,可能要切换ETCD地址,比如主机IP变更。
假设变更的节点为etcd1

操作方式:

  1. 列出etcd节点

etcdctl member list
可以看到
eabc202e74d53d3: name=etcd3 peerURLs=http://172.16.149.124:2380 clientURLs=http://172.16.149.124:2379 isLeader=false
8fa08b2e4744707e: name=etcd1 peerURLs=http://172.16.149.128:2380 clientURLs=http://172.16.149.128:2379 isLeader=false
e50821dfde62301e: name=etcd2 peerURLs=http://172.16.149.123:2380 clientURLs=http://172.16.149.123:2379 isLeader=true

  1. 删除etcd1

etcdctl member remove 8fa08b2e4744707e

  1. 在etcd1上停止etcd服务

systemctl stop etcd

  1. etcd1的IP改好以后,重新加入节点

在etcd2或etcd3上操作
etcdctl member add etcd1 http://xxxxxx:2380

此时,会看到一些要求你配置的信息

  1. 参考4中给出的信息,修改etcd1的/etc/etcd/etcd.conf

  2. 重启etcd1的etcd服务

+6. 修改K3S_DATASTORE_ENDPOINT

因为+5的原因,或某些其他原因,比如要切换一个ETCD集群,或完全切换为Mysql
我们需要修改K3S_DATASTORE_ENDPOINT

修改方式:

vi /etc/systemd/system/k3s.service.env
修改里面的存储地址
systemctl restart k3s

+7. 高可用安装情况下修改80和443端口(本章节网上找不到,纯属原创精华)

如果是单机安装,直接docker的-p就可以解决,但是高可用部署,由于是部署在K3S环境中,因此,不能简单的处理。必须通过修改K3S集群的流量控制入口(说白了,就是Ingress和LoadBanlencer)来处理。

这里,必须先搞清楚(我花了很多时间搞清楚)K3S的流量控制艺术,在搞清楚艺术之前,还得了解Ingress和IngressController,针对Ingress和IngressController,写的最好的文章是我认为写的最好的一篇。

有了Ingress和IngressController的认知之后,我们来看K3S的流量艺术。

  1. K3S默认会安装Traefik作为IngressController,接管集群内80和443的流量。如果看到写的最好的文章,我们就知道,一般情况下,其实IngressController本身并不会(除非特殊的启用hostPort)并不会在主机上监听端口,它依然属于集群内部。
  2. 从写的最好的文章我们知道,让IngressController能够对外服务,可以有三种做法:1)给IngressController开一个NodePort服务;2)IngressController作为DaemonSet部署,暴露hostPort;3)给IngressController暴露一个LoadBalancer服务;
    其实说白了,就是想办法让IngressController这个容器,能够对外暴露服务端口。
    不过,K3S没有采用上面三种做法,它使用了一个特别的办法,在官网我们可以得知(官网中文翻译根本看不懂,难啃),它采用了DaemonSet部署特殊的Klipper Load Balancer进程的方式,来给Traefik Ingress Controller提供流量导入
  3. 2所述的流量导入,可以简单图解为:
    [client]----->(主机port)<—iptables监听—>[DaemonSet-Klipper]—iptables转发—>[集群内Traefik]
    也就是说,K3S通过在每个节点部署Klipper,然后以iptables路由的方式,将节点流量转发到内部的IngressController。
  4. 我们可以在节点中通过
    k3s kubectl get svc -n kube-system
    k3s kubectl get pods -n kube-system
    k3s kubectl get daemonset -n kube-system
    k3s kubectl edit daemonset svclb-traefik -n kube-system
    逐一验证2中所述的官网描述以及通过写的最好的文章所了解到的信息

有了上面的艺术刨析,我们就知道,端口的改造,重点是修改 Daemonset:svclb-traefik,我们从Klipper的github核心文件可以了解到,它是通过iptables来处理流量的。里面使用了一些环境变量来设置入口端口和转发信息
于是:

  1. k3s kubectl edit daemonset svclb-traefik -n kube-system
  2. 修改里面的环境变量端口以及容器端口,主要是环境变量部分
  3. 等待相关POD自动更新

或者,因为了解了刚才的艺术过程。
同样是在官网-ServiceLB如何工作这一节,我们可以得知——由于它使用了
Klipper Load Balancer,因此,你在K3S上创建一个L4负载均衡(即type: LoadBalancer服务),K3S会自动启动一个Klipper Load Balancer,在主机上打开L4负载均衡中设置的服务端口,通过iptables转发你的请求到这个L4负载均衡上面,然后由L4负载均衡再转发到配置的内部端口上。基于这个信息,那么

  1. 打开服务发现,创建一个L4负载均衡,其目标选择POD:traefik
  2. 设置L4负载均衡的服务端口为需要的端口
  3. 保存,等待K3S自动构建svclb-traefik-xxxx

+8. 在Rancher上手动创建Ingress

注意: 此部分前提条件是,集群中部署了IngressContorller且正常运行。

如果是按照此文档部署K3S,默认情况下,会安装Traefik作为IngressContorller。
此时,假设我们要对minio进行Ingress路由发布,操作方式如下:

1、确认minio所在的命名空间

假设命名空间为: minio-ha
2(可选)、为此命名空间安装证书

k3s kubectl -n minio-ha create secret tls ypt-ingress --cert=/root/cert/tls.crt --key=/root/cert/tls.key

其中,minio-ha是命名空间,ypt-ingress是证书名(可按实际情况随意起名),后面的路径是6.4.2中安装的证书相关文件,应该在节点上
3、登录rancher
  3.1、进入项目
  3.2、选择工作负载—>选择负载均衡—>添加规则
  3.2、设置对应的名称
  3.3、选择minio所在的命名空间,这里是minio-ha
  3.4、选择自定义域名---->填写安装集群时证书对应的域名
  3.5、添加规则—>填写合适的路径,比如/minio。选择正确的服务或pod,以及端口
  3.6、展开SSL/TLS证书—>如果2设置了证书,则选择该证书
  3.7、标签可不设置,或按情况设置

至此,集群外可以用过 https://域名:端口/minio 访问到minio的服务

特别说明:
默认情况下,Ingress规则会将路由地址(比如上面的/minio)直接转发到后端服务,如果有些服务必须使用“根路径”或“特别路径”访问,比如minio只能识别/index
那么,处理办法是:
在annonation(也就是“注释”)中,添加一个注释:
traefik.ingress.kubernetes.io/rewrite-target: /index

其中traefik是IngressController的名称(意思是也可能是nginx)

+9. 修改max-pods

如果启动K3S的时候没有指定max-pods(默认110),那么可以手动修改

在需要修改的每个节点上执行

  1. systemctl stop k3s
  2. vi /etc/systemd/system/k3s.service
    这里假设需要修改为200个
  3. 修改 ExecStart=/usr/local/bin/k3s server --docker --kubelet-arg max-pod=200
  4. systemctl daemon-reload
  5. systemctl start k3s

其中参数 --kubelet-arg 是官网提供的参数,其正确格式可以从这里和这里参考

+10. IP修改后,以灾难恢复方式重建ETCD

某些情况下,节点的IP被改变了,此时需要重建ETCD

主要参考官网说明,这里我把完整的试错后的经验记录下来

1、重新启动ETCD单节点

因为此时etcd已经无法正常启动,必须先从一个节点以灾难恢复方式重启

  1. 在准备恢复的节点上修改/etc/etcd/etcd.conf,ETCD_INITIAL_CLUSTER去掉其他节点的信息,只保留当前节点的新IP信息

    并且将里面的所有与IP内容相关的内容修改为正确的新IP
  2. 修改/usr/lib/systemd/system/etcd.service,在ExecStart中,加入--force-new-cluster参数
  3. systemctl daemon-reload && systemctl start etcd

    如果一切正常,ETCD会启动。可通过etcd member list查看情况

2、修改当前节点的peerURLs配置信息

  1. ETCDCTL_API=3 etcdctl member update {上一步etcd member list得到的memberid} --peer-urls=http://新的地址:2380
  2. 修改/usr/lib/systemd/system/etcd.service,在ExecStart中去掉--force-new-cluster
  3. systemctl stop etcd
  4. systemctl daemon-reload && systemctl start etcd

至此,新的ETCD单节点就重建成功

3、重新加入其他etcd节点

  1. 在本节点上执行ETCDCTL_API=3 etcdctl member add {etcdname} --peer-urls=http://{加入节点的地址}
  2. 拿到上一步返回的环境变量

    在前其他ETCD节点上,修改各自的/etc/etcd/etcd.conf,将里面的所有与IP内容相关的内容修改为正确的新IP

    将得到的环境变量修改到/etc/etcd/etcd.conf对应的地方
  3. 在其他ETCD节点上rm -fr /var/lib/etcd/* && systemctl start etcd

4、修改所有节点的配置

依次修改每个节点的/etc/etcd/etcd.conf,将其ETCD_INITIAL_CLUSTER修改为完整的节点信息
依次重启

你可能感兴趣的:(随笔,centos,kubernetes)