k3s笔记-01-部署

Overview

1. 前言

k3s的部署很简单,选择一个Linux系统,执行命令下载脚本进行安装:

1curl -sfL https://get.k3s.io | sh -

安装过程的主要消耗在下载托管在GitHub上的k3s可执行程序。由于最近工作需要在边缘机房部署集群,使用容器化的方式运行服务组件,经过几番考虑选择了k3s,理由如下:

  • 边缘机房资源有限,一部分机房甚至只有2台宿主机,部署k3s对资源要求远低于标准k8s
  • 边缘机房数量较多,每个机房维护一套高可用etcd和k8s代价很高,而k3s在v1.19.5+k3s1版本开始内嵌etcd
  • 容器化服务组件最初的目的就是为了解决服务本身高可用问题,服务组件数量不多,不需要CNI也不需要Service,简化后的k3s已经够用
  • k3s本身集成了api-server、scheduler、controller-manager、etcd、containerd...等等,一个可执行文件中包含了所有必须的组件,无需再拉取镜像

因为需要针对边缘机房环境进行定制化并输出部署脚本,这里就先研究了下k3s的安装。

2. 安装脚本分析

这里保存一个安装脚本的备份:get-k3s-io.sh

安装脚本很长,但是写的非常工整漂亮,可以看到主要安装步骤如下:

 1# --- run the install process --
 2{
 3    verify_system
 4    setup_env "[email protected]"
 5    download_and_verify
 6    setup_selinux
 7    create_symlinks
 8    create_killall
 9    create_uninstall
10    systemd_disable
11    create_env_file
12    create_service_file
13    service_enable_and_start
14}
  1. 检查系统:查看系统是否支持使用openrc或systemd运行程序
  2. 环境变量解析: K3S_ 开头的环境变量会传递给k3s可执行程序使用,INSTALL_ 开头的环境变量由安装脚本使用,可控制安装操作,如版本、安装目录、是否下载二进制文件等等
  3. 下载与验证k3s:从github或google下载当前环境所需的k3s可执行文件,若配置 INSTALL_K3S_SKIP_DOWNLOAD=true,可跳过下载
  4. 配置selinux:若启用了selinux,需要额外安装一些软件
  5. 创建软链接:创建kubectl、crictl、ctr等软链接,指向k3s可执行程序,执行命令时会启用对应功能
  6. 创建k3s-killall.sh脚本:执行 k3s-uninstall.sh 时会被调用,该脚本会停止k3s相关systemd服务,杀死所有k3s管理的容器组,解除k3s相关目录挂载并删除,移除CNI、移除k3s创建的iptables规则
  7. 创建k3s-uninstall.sh脚本:k3s卸载脚本,首先执行k3s-killall.sh,然后从系统中彻底卸载k3s
  8. 停止已加载的k3s服务
  9. 创建环境变量文件:将 K3s_ 开头的环境变量写入文件
  10. 创建service文件:根据系统支持,创建对应的systemd或openrc的service文件
  11. 启动k3s:启动k3s并设置为开机自动启动

示例:

1curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_DOWNLOAD=true INSTALL_K3S_EXEC="server" sh -s - --disable coredns,servicelb,traefik,local-storage,metrics-server --disable-kube-proxy --disable-network-policy --no-flannel --cluster-init --cluster-cidr 10.253.0.0/16 --service-cidr 10.254.0.0/16 --container-runtime-endpoint unix:///run/containerd/containerd.sock --node-name 10-0-0-1 --node-ip 10-0-0-1

环境变量需要设置在 sh -s - 之前,其中 INSTALL_ 开头的环境变量控制了安装脚本的操作,因为k3s启动参数繁杂,这里不使用 K3S_ 开头的环境变量进行自定义配置,统一改为在 sh -s - 后传入参数,这些参数在debian 10下会持久化到文件 /etc/systemd/system/k3s.service 中,在ExecStart启动k3s时,作为参数传入,如下:

 1➜  ~ cat /etc/systemd/system/k3s.service
 2...
 3ExecStart=/usr/local/bin/k3s \
 4    server \
 5	'--cluster-init' \
 6	'--cluster-cidr' \
 7	'10.253.0.0/16' \
 8	'--service-cidr' \
 9	'10.254.0.0/16' \
10...

在安装后如果有需要增加其他启动参数,可修改service文件,重新加载后重启k3s即可。在生产环节中,为了简化部署,笔者主要做了以下调整:

  1. 预安装k3s二进制文件,跳过下载:规避了github和谷歌在国内的访问问题
  2. 移除所有附加组件、kube-proxy、CNI插件:我们的生产环节无法部署依赖service的服务,统一使用hostNetwork与自研的DNS服务
  3. 使用外置CRI:k3s提供了模板功能来自定义内嵌的containerd参数,但是生产环节中宿主机环境复杂,笔者使用了独立部署的containerd和预启动脚本来处理这些差异

3. k3s内嵌组件分析

首先看一下k3s的帮助命令,如下:

 1➜  ~ k3s --help
 2NAME:
 3   k3s - Kubernetes, but small and simple
 4
 5USAGE:
 6   k3s [global options] command [command options] [arguments...]
 7
 8VERSION:
 9   v1.21.5+k3s2 (724ef700)
10
11COMMANDS:
12   server         Run management server
13   agent          Run node agent
14   kubectl        Run kubectl
15   crictl         Run crictl
16   ctr            Run ctr
17   check-config   Run config check
18   etcd-snapshot  Trigger an immediate etcd snapshot
19   help, h        Shows a list of commands or help for one command
20
21GLOBAL OPTIONS:
22   --debug                     (logging) Turn on debug logs [$K3S_DEBUG]
23   --data-dir value, -d value  (data) Folder to hold state default /var/lib/rancher/k3s or ${HOME}/.rancher/k3s if not root
24   --help, -h                  show help
25   --version, -v               print the version
  1. server:运行控制节点的子命令,有大量参数可定义控制平面组件,使用HA模式时需要注意所有master除宿主机相关参数外必须一致,由于参数繁多,笔者不推荐使用环境变量的方式传参
  2. agent:运行工作节点的子命令
  3. kubectl:kubectl子命令,可调用api-server与集群交互
  4. crictl:容器组管理子命令,可调用k3s使用CRI接口
  5. ctr:容器管理子命令,可调用k3s使用的containerd
  6. check-config:配置检查子命令
  7. etcd-snapshot:etcd快照管理子命令,可触发etcd生成快照,备份至本地或远端s3服务

从宏观上讲,k3s的集群中只有server与agent两种角色,agent的功能是server的子集,其他的子命令都属于辅助工具,下面分别展开agent和server的功能。

k3s agent

  • kubelet:kubelet功能,实现k8s工作节点的所有功能
  • flannel:k3s内嵌flannel作为默认集群通信方案
  • kube-proxy:k3s内嵌kube-proxy,而非使用独立的kube-proxy组件
  • containerd:k3s内嵌containerd作为默认CRI,也可以使用外部CRI
  • lb:访问apiserver的本地lb,注意不是service中定义的load balancer
  • 宿主机工具:包含修改宿主机环境所需的工具如iptables、ethtool等等

k3s server

  • agent:server包含所有agent功能
  • 控制平面组件:
    • kube-apiserver:提供Kubernetes API
    • kube-scheduler:提供Pod调度功能
    • kube-controller-manager:管理标准控制器,如Node Controller、Job Controller...
    • cloud-controller-manager:管理对接云厂商的控制器
  • 数据库组件:
    • sqlite:k3s封装了sqlite作为默认KV数据库
    • etcd:k3s在v1.19.5+k3s1版本后内嵌了etcd,并可在初始化时启用
  • k3s组件:
    • helm-controller:helm控制器
    • servicelb:服务lb组件,支持通过宿主机端口暴露service

以上是仅使用k3s二进制文件部署集群能得到的所有功能。

4. k3s附加组件分析

附加组件使用yaml部署以Pod形式运行,如下:

  1. coredns:提供DNS和服务发现
  2. servicelb:提供服务负载均衡功能,在k3s中利用宿主机端口暴露service
  3. traefik:实现k8s ingress controller,提供服务暴露功能
  4. local-storage:使用hostPath提供本地持久化存储卷
  5. metrics-server:k8s资源指标健康服务

这些都属于可选可替换的组件,对应的yaml存放在 /var/lib/rancher/k3s/server/manifests 中。

5. HA

k3s提供了两种高可用的部署方式,核心还是如何保障DB的高可用,如下:

1. 使用外部DB

High Availability with an External DB

要求:

  1. 部署2个或以上server
  2. 部署N个agent
  3. 部署一个高可用的外部数据库,如etcd、MySQL、PostgreSQL等
  4. 部署一个固定注册地址对agent暴露server,如:四层TCP负载均衡器、DNS、VIP或EIP

这种比较适合云主机环境,边缘机房的缺乏相关的基础设施。

2. 使用内嵌ETCD

High Availability with Embedded DB

要求:

  1. k3s版本v1.19.5+k3s1及以上
  2. 部署奇数个server,推荐3个及以上
  3. 保持这些参数在所有server上一致
    1. 网络相关参数:--cluster-dns, --cluster-domain, --cluster-cidr, --service-cidr
    2. 控制特定组件部署的参数:--disable-helm-controller, --disable-kube-proxy, --disable-network-policy,--disable
    3. 特性相关参数:--secrets-encryptio

这种方式是笔者目前采用的,etcd跟随server部署,无需分开维护DB与apiserver,一定程度上简化了部署和运维,但实现DB高可用所需的工作并不会减少,笔者将会在下一篇中记录实践情况。

comments powered by Disqus