K3s 上手 - 集群搭建

2021-07-06 [基础设施] #K3s #K8s #Kubernetes #Traefik #Homelab #Wireguard

《PVE 中虚拟化万兆网卡》中我有提到自己攒了台双路的机器放在家里,长期以来作为我远程的 Power 机器,在上面用 Docker-Compose 跑我的各种服务。从攒好机器到现在,反复多次搭建 Kubernetes,最终都放弃了:上手成本的确高

是否要用 Kubernetes 取代 Docker-Compose ?

从理性的角度来说,Docker-Compose 完全胜任,简单,好用,完全没必要。然而在 Kubernetes 大行其道的今天,感性方面告诉我一定要跟着大家上高端的 Kubernetes…

最近有又冒出了想用 Kubernetes 的想法,在几经犹豫之后,最终决定本次一定不能中途放弃!!!为了减少搭建复杂度和资源的占用,本次选择了K3s

The certified Kubernetes distribution built for IoT & Edge computing.

K3s 是一个 Kubernetes 认证的发行版,可以理解为一个轻量级的 K8s,K3s 的架构如下:

Hot it works - k3s

集群规划

集群规划有两点需要考虑:

  1. 是否要上HA:不需要,所有 VM 都通过 PVE 跑在一台物理机上,没必要上 HA。
  2. 数据如何存储:各节点的所有数据均通过 NFS 存储到 NAS 中,每个节点仅提供操作系统必须的磁盘空间即可。

我的规划中,共4个节点,每个节点相同配置:4C 8G,细节如下:

HostNameCPUMemoryDiskOSIP
k3s-server48G5GDebian 10 (5.10.40-1~bpo10+1)192.168.2.21
k3s-worker-0148G5GDebian 10 (5.10.40-1~bpo10+1)192.168.2.22
k3s-worker-0248G5GDebian 10 (5.10.40-1~bpo10+1)192.168.2.23
k3s-worker-0348G5GDebian 10 (5.10.40-1~bpo10+1)192.168.2.24

前期准备

节点间互相访问

以下为 k3s-server 的配置,其他 worker 节点同理,手动配置略麻烦,有兴趣的可以使用 ansible 批量操作。

k3s-server # cat /etc/hosts
...
192.168.2.6     nas             # 我自建的NAS
192.168.2.22    k3s-worker-01
192.168.2.23    k3s-worker-02
192.168.2.24    k3s-worker-03
...

能顺畅访问 docker-hub, gcr.io, k8s-gcr.io

网络问题真的令人头疼,虽然 K3s 跑起来很简单,但避免不了后续需要从以上几个 Registry 中拉取镜像,所以建议第一步先 自建一个统一的代理,可以使用我整理的一键安装脚本,详见: registry on k3s

以下为该安装脚本的使用步骤:

  1. 拥有一台可以访问 gcr.io, k8s-gcr.io… 并且有公网 IP 的机器

  2. 在机器上拉取本仓库: git clone https://github.com/eightpigs/proxy_registry_k3s

  3. 根据代理情况修改 run.sh 的前几行配置,默认创建 hub.docker.io, gcr.io, k8s-gcr.io 3个代理

    如果要代理 hub.docker.io 请自行更换以下信息:

    • UserName : pod-hub-registry.yaml:72
    • Password: pod-hub-registry.yaml:74
  4. 运行: ./run.sh,运行结束后会有如下输出表示相关仓库配置成功:

hub-k3s.io => HTTP/1.1 200 OK
gcr-k3s.io => HTTP/1.1 200 OK
k8s-gcr-k3s.io => HTTP/1.1 200 OK
  1. 使用 ansible 对自有 K3s 集群的所有节点配置代理

    • 记得在 $ANSIBLE_INVENTORY 中配置 k3s 相关 hosts
    • 运行过程中,会询问 第一步 服务器的公网IP,填入即可
ansible-playbook ansible-add-registry.yaml -K
  1. Enjoy it

搭建 K3s 单 Master 集群

相比使用 kubeadm 搭建 K8s 集群的复杂度而言,K3s 集群搭建是真的简单,仅一行命令:

# 创建 server
k3s-server # curl -sfL https://get.k3s.io | sh -

# 运行 worker 并加入 集群
k3s-workers # curl -sfL https://get.k3s.io | K3S_URL=https://k3s-server:6443 K3S_TOKEN=mynodetoken sh -

看起来如此简单,但当我将集群配置好开始运行 Pod 时,不同节点的 Pod 无论如何也不能互相访问,困扰了我好几天,最终我选择放弃研究(开始萌生退意了),打算不再使用官方的一键安装脚本,转而手动安装并使用 Wireguard 来做 flannel-backend。

由于安装脚本较长,限于篇幅,可以在此 Github 仓库查看整理好的 Playbook,详见: k3s-ansible-playbooks

K3s 运行仅需要一个编译好的单文件,所以手动搭建过程主要分为2步:

  1. 下载 k3s 二进制文件 && 安装 Wireguard
  2. 配置 Systemd
# 下载 k3s 二进制文件 && 安装 Wireguard
- hosts: k3s
  remote_user: dev
  become: yes
  gather_facts: False
  tasks:
    - set_fact:
        k3s_version: "v1.21.2+k3s1"
        ip_link: ens18
    - name: Output K3s Version
      debug: msg="{{ k3s_version }}"
      when: k3s_version is defined
    - name: Download K3s
      shell: |
        ls /usr/local/bin/k3s > /dev/null 2>&1 || wget "https://github.com/k3s-io/k3s/releases/download/{{ k3s_version }}/k3s" -O /usr/local/bin/k3s
        chmod +x /usr/local/bin/k3s
      when: k3s_version is defined
    - name: Install Wireguard
      shell: |
        which wg > /dev/null 2>&1 || apt install wireguard -y

以下仅是 k3s-server,k3s-workers 安装详见 Github 仓库: k3s-ansible-playbooks

# 配置 k3s-server Systemd
- hosts: k3s-master
  remote_user: dev
  become: yes
  gather_facts: False
  tasks:
    - name: Check K3s Server Installed
      shell: ls /etc/systemd/system/k3s.service > /dev/null 2>&1 && echo 1 || echo 0
      register: server_installed
    - name: Get IP
      shell: ip addr show {{ ip_link }} | grep inet | head -n 1 | awk '{print $2}' | sed -e 's/\/[0-9]\+//g'
      register: ip_addr
    - name: Output IP Addr
      debug: msg="IP {{ ip_addr.stdout }}; Installed {{ server_installed.stdout }}"
      when: ip_addr is defined and ip_addr.rc == 0
    - name: Create K3s.service.env
      command: touch /etc/systemd/system/k3s.service.env
      when: server_installed is defined and server_installed.stdout == '0'
    - name: Create K3s Server System Unit
      when: ip_addr is defined and ip_addr.rc == 0 and server_installed is defined and server_installed.stdout == '0'
      shell: |
        cat > /etc/systemd/system/k3s.service <<EOF
        [Unit]
        Description=Lightweight Kubernetes
        Documentation=https://k3s.io
        Wants=network-online.target

        [Install]
        WantedBy=multi-user.target

        [Service]
        Type=notify
        EnvironmentFile=/etc/systemd/system/k3s.service.env
        KillMode=process
        Delegate=yes
        # Having non-zero Limit*s causes performance problems due to accounting overhead
        # in the kernel. We recommend using cgroups to do container-local accounting.
        LimitNOFILE=1048576
        LimitNPROC=infinity
        LimitCORE=infinity
        TasksMax=infinity
        TimeoutStartSec=0
        Restart=always
        RestartSec=5s
        ExecStartPre=-/sbin/modprobe br_netfilter
        ExecStartPre=-/sbin/modprobe overlay
        ExecStart=/usr/local/bin/k3s \
            server \
            --tls-san {{ ip_addr.stdout }} \
            --node-ip {{ ip_addr.stdout }} \
            --node-external-ip {{ ip_addr.stdout }} \
            --no-deploy servicelb \
            --write-kubeconfig-mode=644 \
            --flannel-backend wireguard \
            --kube-proxy-arg "proxy-mode=ipvs" "masquerade-all=true" \
            --kube-proxy-arg "metrics-bind-address=0.0.0.0"
        EOF
    - name: Enable K3s Systemed
      command: systemctl enable k3s --now
      when: server_installed is defined and server_installed.stdout == '0'
    - name: get server token
      command: cat /var/lib/rancher/k3s/server/node-token
      register: server_token
    - name: output server token
      debug: msg="{{ server_token.stdout }}"
      when: server_token is defined and server_token.rc == 0

安装完成后,可以使用 kubectl get nodes -o wide 查看所有节点信息

NAME            STATUS   ROLES                  AGE   VERSION        INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION         CONTAINER-RUNTIME
k3s-worker-02   Ready    <none>                 46d   v1.21.2+k3s1   192.168.2.23   <none>        Debian GNU/Linux 10 (buster)   5.10.0-0.bpo.7-amd64   containerd://1.4.4-k3s2
k3s-master      Ready    control-plane,master   46d   v1.21.2+k3s1   192.168.2.21   <none>        Debian GNU/Linux 10 (buster)   5.10.0-0.bpo.7-amd64   containerd://1.4.4-k3s2
k3s-worker-01   Ready    <none>                 46d   v1.21.2+k3s1   192.168.2.22   <none>        Debian GNU/Linux 10 (buster)   5.10.0-0.bpo.7-amd64   containerd://1.4.4-k3s2
k3s-worker-03   Ready    <none>                 46d   v1.21.2+k3s1   192.168.2.24   <none>        Debian GNU/Linux 10 (buster)   5.10.0-0.bpo.7-amd64   containerd://1.4.4-k3s2

Next: K3s 上手 - NFS 存储配置

文章作者:eightpigs
创作时间:2021-07-06
更新时间:2021-08-27
许可协议:CC by-nc-nd 4.0