[分享】使用k3s 和 tailscale 在甲骨文云和家之间搭建 kubernetes集群

最近一直在学习 kubernetes(k8s)相关的知识,为了实践学到的知识,选用了 k3s 作为实际部署集群的工具,已经为位于美国的四台虚拟机搭建了一个集群,这四台虚拟机中将一台 2 核 3G 的作为 server,满足了 k3s 的最低硬件要求,目前工作良好。

不过我本来想把自己闲置的甲骨文机器也搞个集群的,但是发现甲骨文的机器似乎作为 server 有点吃力。

由于手上没有其他更高配置的虚拟机,灵光一闪,决定直接在家里 pve 里面搞一台虚拟机作为 k3s server,然后通过 tailscale 来连通所有的甲骨文机器。需要使用 tailscale 主要有两个原因:

  1. 家里没有公网 IP,所以甲骨文的虚拟机无法直接和它通信,所以借助万能的 tailscale 来组网,实现一个 k3s over tailscale 的效果。
  2. 甲骨文给的虚拟机,虽然有公网 ip,外部访问虚拟机 ip 能正确的获得响应,但这个公网 IP 不是直接给虚拟机的,所以虚拟机查看网卡的 ip 得到的是局域网的 ip,所以对于虚拟机来说,它也算没有公网。

tailscale 作为内网穿透利器,有很多免费的中继服务器。并且 k3s 对 tailscale 的支持也是开箱即用的。

具体步骤:

一:配置家里的 k3 server

server 位于家中,作为集群的控制中心。通过 pve 的模版 快速创建了一个操作系统,我安装的是 ubuntu 22。

安装完系统之后,ssh 进入创建的虚拟机。然后执行下面的步骤:

  1. 安装 tailscale: curl -fsSL https://tailscale.com/install.sh | sh

  2. 安装 k3s server: curl -sfL https://get.k3s.io | sh -

  3. 获取 k3s token:cat /var/lib/rancher/k3s/server/node-token, 将结果作为 K3S_TOKEN 保存

  4. 创建 tailscale auth token,后面 agent 使用 tailscale 连接需要的授权信息,结果作为 TAILSCALE_TOKEN

  5. 配置 tailscale 的 nameserver(这个步骤似乎可以不做)

  6. 新增 k3s 配置文件 /etc/rancher/k3s/config.yaml ,里面的内容修改为:

vpn-auth: "name=tailscale,joinKey=${TAILSCALE_TOKEN}"

你需要将 ${TAILSCALE_TOKEN} 替换为第四步获得的实际值。

  1. 修改完配置文件重启服务 sudo systemctl restart k3s

二:验证 k3s server 已经通过 tailscale 连接

接着我们需要确保安装的 k3s 服务正确的使用了 tailscale,这样才能让后面连上 tailscale vpn 的机器都能讲它作为 server。

通过 sudo kubectl get node

你应该能看到一个 master 节点已经就绪,类似:

ubuntu@k3s-jp-home-server:~$ sudo kubectl get node
NAME                     STATUS   ROLES                  AGE    VERSION
k3s-jp-home-server       Ready    control-plane,master   1m   v1.27.5 k3s1

我这台主机叫 k3s-jp-home-server,它就是当前虚拟机的 hostname

  1. 通过 sudo kubectl describe node k3s-jp-home-server查看这个节点的细节信息,留意里面的 ip,我这里获取到的 IP 是 100.91.43.90:

  2. 获取当前 tailscale 的节点的 IP:sudo tailscale status 找到这台刚刚注册的这台机器的 ip,不出意外的话这个 ip 就是上面截图的 ip。我们将这个 IP 记做 TAILSCALE_IP

  3. 最后通过 curl -vk https://100.91.43.90:6443/cacerts (替换成你自己的 ip),应该能看到 k3s server 生成的自签名证书。将 https://100.91.43.90:6443 作为 K3S_URL

到这里我们就拥有了一个在 tailscale vpn 下面可用的 k8s 主节点。

三:在甲骨文云配置 k3s agent

  1. 进入甲骨文云管理后台,新建一条规则,允许所有协议(相当于关闭了防火墙)
  2. ssh 登陆到虚拟机,删除 ubuntu iptable 加载器,升级 iptable 并重启
    apt-get remove iptables-persistant
  3. 安装 tailscale: curl -fsSL https://tailscale.com/install.sh | sh
  4. 运行 tailscale:tailscale up 这样才能连接到 家里的 server
  5. 通过 tailscale status 确认状态正常,然后通过 curl 确认甲骨文能通过 tailscale 连接到家里的 server:
    curl -vk https://100.91.43.90:6443/cacerts
    能看到自签名证书后,说明甲骨文能连接到家里的 server 了。
  6. 安装 k3s agent:
export K3S_URL=https://100.91.43.90:6443
export K3S_TOKEN=Kxxx::server:xxx
curl -sfL https://get.k3s.io | K3S_URL=${K3S_URL} K3S_TOKEN=${K3S_TOKEN} sh -
  1. 配置 k3s 使用 tailscale。和配置 server 一样,新增文件/etc/rancher/k3s/config.yaml,里面的内容修改为vpn-auth: "name=tailscale,joinKey=${TAILSCALE_TOKEN}"
  2. 重启 k3s agent 使得刚刚的配置生效:sudo systemctl restart k3s-agent

四:验证 k3s agent 成功加入集群

回到家里的终端在通过 sudo kubectl get node 应该能看到刚刚加入的机器。

❯ kubectl get node
NAME                     STATUS   ROLES                  AGE     VERSION
k3s-jp-home-server       Ready    control-plane,master   30m   v1.27.5 k3s1
instance-20220922-2113   Ready                     3m    v1.27.5 k3s1

我这里多出来了一台 instance-20220922-2113

同时通过 sudo kubectl describe node instance-20220922-2113 查看加入的 agent 的 ip,应该是 tailscale 提供的 ip 范围(100.64.0.0/10)而不是甲骨文的内网 ip(比如 10.0.0.x)

按照上述方法把自己剩下的甲骨文加到这个集群后的效果:

到这里,我们就把所有的免费甲骨文加到集群里面去了。

五:验证 k3s 集群功能正常

部署一个最简单的 whoami 验证一下集群里面各台机器的联通性 (它的原始文件来自 这里,镜像从 nginx 换成了 whoami,方便查看 pod 信息)

新建一个 traefik.yaml 文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: traefik/whoami
          ports:
            - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080
  type: NodePort

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  rules:
    - host: nginx.tomyail.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 80

这个配置大致的意思就是新建五个 pod,然后用名字是 nginx-service 的服务 连接这五个 pod,对外暴露一个 ip,最后通过 ingress 将 http 流量路由到这个 nginx-service 服务。新建五个是因为我有五个 node,所以他们大概率会分散到每台机器上。(k8s 如何将 pod 分配到 node 的策略有一堆配置可以学习呢)

之后 sudo kubectl apply -f traefik.yaml 执行部署。稍等片刻查看部署状态:sudo kubectl get pod -o wide

ubuntu@k3s-jp-home-server:~$ sudo kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS      AGE   IP           NODE                     NOMINATED NODE   READINESS GATES
nginx-deployment-58ffdc8f48-qzwrb   1/1     Running   0             26h   10.42.2.7    oracle-korea-2                      
nginx-deployment-58ffdc8f48-7r4bt   1/1     Running   0             26h   10.42.1.6    oracle-korea-1                      
nginx-deployment-58ffdc8f48-525k6   1/1     Running   0             26h   10.42.0.12   k3s-jp-home-server                  
nginx-deployment-58ffdc8f48-cgzlf   1/1     Running   0             23h   10.42.3.3    oracle-toyko-1                      
nginx-deployment-58ffdc8f48-blmh6   1/1     Running   3 (22h ago)   23h   10.42.4.8    instance-20220922-2113              

在 server 的机器上,curl 上面这几个 ip,看到下面的这些信息就表示集群里面的 whoami 部署成功了

ubuntu@k3s-jp-home-server:~$ curl 10.42.3.3
Hostname: nginx-deployment-58ffdc8f48-cgzlf
IP: 127.0.0.1
IP: ::1
IP: 10.42.3.3
IP: fe80::645a:46ff:fe5d:e2f3
RemoteAddr: 10.42.3.1:56192
GET / HTTP/1.1
Host: 10.42.3.3
User-Agent: curl/7.58.0
Accept: */*

最后就是进入 cloudflare,为刚刚的 nginx 服务增加一条 dns A 记录,这个记录的 IP 可以是任何一个集群里面有公共 ip 的机器。当然你可以选择用一些自动化工具来自动根据 ingress 自动更新 cloudflare dns 记录,比如 external-dns

最后你就可以通过 nginx.tomyail.com 访问我部署的这个服务了。

如果你希望看到包含图文的更详细文章,欢迎访问我的博客:使用k3s 和 tailscale 在甲骨文云和家之间搭建 kubernetes集群

点赞
  1. xiaxialong说道:

    学习了

  2. hai125698说道:

    好文绑定

  3. ekkosky说道:

    学习

回复 ekkosky 取消回复

电子邮件地址不会被公开。必填项已用 * 标注

×
订阅图标按钮