超长干货!在裸机上配置高可用K3s,部署生产就绪工作负载

边缘计算k3s社区

共 6201字,需浏览 13分钟

 · 2020-12-27

作者简介

Alex Ellis,OpenFaaS联合创始人、CNCF大使、k3sup创建者


这篇教程是基于2017年《10分钟内在裸机上运行Kubernetes》的文章,您可以访问以下链接查看之前的教程:

https://blog.alexellis.io/kubernetes-in-10-minutes/


之前的教程主要聚焦于让Kubernetes在运行Ubuntu的裸机主机上运行,然后部署微服务和仪表盘。这只是一个初级阶段,并且当初写下那篇文章目的是为了让初学者能够简单上手Kubernetes。在文章里使用了生产就绪的kubeadm,但只使用了一个主节点,这意味着它无法容忍失败。


在本文中,我将向你提供一个在裸机基础设施上高可用、生产就绪的集群。我们将使用Equinix Metal作为主机,将比较枯燥的操作部分自动化,剩下的流程我们将一步一步完成,以便您可以了解底层的情况。


总而言之,我们将重温一遍相关设置并讨论其他选项,以便在本地或homelab中使用树莓派运行。我们还将比较kube-vip与其他裸机和自托管网络的解决方案。


由稳定的EIP提供的kubectl访问。IngressController也有一个EIP,它为Ingress暴露的服务(如OpenFaaS网关)路由流量。


本文也从kubeadm转向使用K3s,因为K3s的控制平面所需资源较少,并且使用嵌入式的etcd内置HA模式。2019年11月,K3s已经GA,可以用于生产。


教程正式开始!


我们将使用Terraform在Equinix Metal (又名 Packet) server 上创建节点,k3s创建一个高可用的控制平面以及使用kube-vip来为API Server配置一个高可用的IP地址。


这一设置将能够容忍至少一个server故障。所以与2017年那篇文章有所不同,我们的server将形成一个高可用集群并且也将拥有一个配置好的EIP以便如果一个或多个服务器不可以,Kubernetes API server仍然可以访问。


在Kubernetes集群中,Cloud Controller Manager插件将执行几个功能,包括节点管理、路由以及管理服务。在本教程的最后,你的集群不仅可以拥有一个高可用控制平面、一个为API server提供的稳定IP,而且Equinix Metal 的 CCM还将允许您将服务暴露为 LoadBalancer 类型。每个IP地址将花费大约23元/月,你可以在仪表盘的IP地址部分找到更多细节。


安装的前期准备


下载arkade (https://get-arkade.dev/),一个便携式的Kubernetes marketplace和DevOps CLI下载器。它将被用来下载我们教程中所需要的工具。


curl -sLS https://dl.get-arkade.dev | sh
# Install the binary using the command given as output, such as: sudo cp arkade-darwin /usr/local/bin/arkade
# Or on Linux:sudo cp arkade /usr/local/bin/arkade


下载以下CLIS:


  • kubectl— Kubernetes CLI

  • k3sup— 通过SSH工作的k3s安装程序

  • Terraform— 基础设施即代码(IaC)工具,我们将用其创建初始主机

  • kubectx—能够在集群间快速检查和切换你的Kubernetes上下文(context)


arkade get kubectlarkade get k3suparkade get terraformarkade get kubectx


根据这一步将这些二进制文件放到你的PATH:


# Add (k3sup) to your PATH variableexport PATH=$PATH:$HOME/.arkade/bin/


配置你的节点


我们将使用terraform来配置三个server和2个agent。这并不是固定的数量,你可以根据自身需求进行选择,但是对于K3s使用etcd的内置高可用模式来说3是最小的数字。


你可能会问为什么整篇文章不直接用一条Terraform命令就完成所有步骤呢。因为这篇文章的重点并不是要为您完成所有工作,而是帮助您了解需要做什么、按什么顺序做。创建主机是很枯燥的,所以我们要把它自动化,为您节省一些时间。


使用以下命令保存main.tfvars


terraform {  required_providers {    packet = {      source = "terraform-providers/packet"      version = "~> 3.2.1"    }  }  required_version = ">= 0.13"}
variable "api_token" { description = "Equinix Metal API token"}
variable "project_id" { description = "Equinix Metal Project ID"}
variable "servers" { description = "Count of servers"}
variable "agents" { description = "Count of agents"}
provider "packet" { auth_token=var.api_token}
resource "packet_ssh_key" "key1" { name = "k3sup-1" public_key = file("/home/alex/.ssh/id_rsa.pub")}
resource "packet_device" "k3s-server" { count = var.servers hostname = "k3s-server-${count.index+1}" plan = "c1.small.x86" facilities = ["ams1"] operating_system = "ubuntu_20_10" billing_cycle = "hourly" project_id = var.project_id depends_on = [packet_ssh_key.key1]}
resource "packet_device" "k3s-agent" { count = var.agents hostname = "k3s-agent-${count.index+1}" plan = "c1.small.x86" facilities = ["ams1"] operating_system = "ubuntu_20_10" billing_cycle = "hourly" project_id = var.project_id depends_on = [packet_ssh_key.key1]}
output "server_ips" { value = packet_device.k3s-server.*.access_public_ipv4}
output "agent_ips" { value = packet_device.k3s-agent.*.access_public_ipv4}


然后创建main.tfvars


api_token   =   ""project_id  =   ""servers     =   3agents      =   2


使用来自Equinix Metal仪表盘的值编辑api_tokenproject_id。在你的user profile上找到API key。


如果你希望更改节点规模,你可以编辑c1.small.x86并且使用一个不同的值。你可以在仪表盘上找到该选项。


现在运行terraform来创建主机:


terraform initterraform plan -var-file=main.tfvarsterraform apply -var-file=main.tfvars


当主机创建之后,你将获得你的IP地址的输出。


agent_ips = [  "147.75.81.203",  "147.75.33.3",]server_ips = [  "147.75.32.35",  "147.75.80.83",  "147.75.32.99",]


打开一个terminal并为每个组件写环境变量:


export SERVER1=""export SERVER2=""export SERVER3=""
export AGENT1=""export AGENT2=""


将该文件保存为hosts.txt,因为你稍后可能需要它。


获取控制平面IP地址


K3s可以在HA模式下运行时可以容忍一个主节点的故障。这对于公共的集群来说是不够的,因为在这种情况下,Kubernetes控制平面需要一个稳定的IP地址。


我们需要为6443端口提供稳定的IP,我们也可以称之为弹性IP或EIP。幸运的是,BGP可以帮助我们。我们的三个主节点中的其中一个会宣传它的IP地址作为EIP的路由,然后如果它宕机了,另一个就会开始宣传。这意味着我们的客户可以使用依靠一个稳定的地址:https://$EIP:6443来连接Kubernetes API server。


从你的EM仪表盘获取IP地址:


  • IP及网络

  • 请求IP地址

  • 选择你将用于节点的同一区域

  • 选择一个/32作为控制平面的单个IP


工程师可能需要一些时间来批准这个请求。拥有IP之后,在环境变量中设置它:


export EIP="147.75.100.237"


添加这条命令到hosts.txt中,这样你就可以保存它,便于你以后需要。


为每个Server启用BGP


单击 Equinix Metal 仪表板中的每台服务器。单击其详细信息页面,然后单击 BGP。在 IPv4 行中找到管理按钮,并单击 "启用 BGP"。


此设置允许从该服务器发布 BGP 。


配置第一个主节点


由于各种原因,我们只能在K3s启动后才能设置kube-vip,所以我们将创建第一个主节点:


k3sup install \  --ip $SERVER1 \  --tls-san $EIP \  --cluster \  --k3s-channel latest \  --k3s-extra-args "--no-deploy servicelb --disable-cloud-controller" \  --merge \  --local-path $HOME/.kube/config \  --context=em-ha-k3s


  • --tls-san是需要宣传EIP的,这样K3s将为API服务器创建一个有效的证书。

  • --k3s-channel可以指定K3s的最新版本,在本例中是1.19。当你运行本教程时,它可能已经更改为更新的版本,在这种情况下,你可以给1.19作为channel,或者用--k3s-version指定一个特定的版本。

  • 请注意 --cluster 标志,它告诉服务器使用 etcd 为我们稍后要加入的服务器创建一个集群

  • --local-path--context--merge 都允许我们将 K3s 中的 KUBECONFIG 合并到我们的本地文件中。

  • --k3s-extra-args 中,我们禁用了内置的 K3s 服务负载均衡器,还禁用了 cloud-controller,因为我们将使用 Equinix Metal Cloud Controller Manager 来代替。


现在检查你的kubeconfig文件是否指向正确的集群:


kubectx em-ha-k3s


尝试在集群中查询节点:


[alex@nuc ~]$ kubectl get nodesNAME           STATUS     ROLES         AGE   VERSIONk3s-server-1   Ready      etcd,master   7s    v1.19.5+k3s2


应用RBAC以便kube-vip可以访问Kubernetes API并配置服务:


kubectl apply -f https://kube-vip.io/manifests/rbac.yaml


现在使用SSH登录到第一台服务器。每个服务器都需要一个一次性配置选项。


ssh root@$SERVER1
ctr image pull docker.io/plndr/kube-vip:0.3.0
alias kube-vip="ctr run --rm --net-host docker.io/plndr/kube-vip:0.3.0"export INTERFACE=loexport EIP="147.75.100.237"
kube-vip vip /kube-vip manifest daemonset \ --interface $INTERFACE \ --vip $EIP \ --controlplane \ --services \ --inCluster \ --taint \ --bgp \ --packet \ --provider-config /etc/cloud-sa/cloud-sa.json | tee /var/lib/rancher/k3s/server/manifests/vip.yaml


Kube-vip的manifest将在/var/lib/rancher/k3s/server/manifests/vip.yaml处创建,任何放在这里的文件都将由K3s运行。


登出服务器。


部署Equinix Metal 

Cloud Controller Manager


现在部署Equinix Metal Cloud Controller Manager (CCM),它将创建上述命令中引用的/etc/cloud-sa/cloud-sa.json文件。按照配置,CCM将从Equinix Metal API获取任何暴露的服务的IP地址。


创建一个secret,如下所示:


export API_KEY=""export PROJECT_ID=""
cat < ccm-secret.yamlapiVersion: v1kind: Secretmetadata: name: packet-cloud-config namespace: kube-systemstringData: cloud-sa.json: | { "apiKey": "$API_KEY", "projectID": "$PROJECT_ID" }EOF


现在应用该secret,然后使用kube-vip修改CCM:


kubectl apply -f ./ccm-secret.yamlkubectl apply -f https://gist.githubusercontent.com/thebsdbox/c86dd970549638105af8d96439175a59/raw/4abf90fb7929ded3f7a201818efbb6164b7081f0/ccm.yaml


该要旨包含一个 Equinix Metal CCM 的分叉版本。这是由 kube-vip 的作者开发的,并将被上游化,届时 URL 将重定向至 CCM 的原始 repo:

https://github.com/packethost/packet-ccm


检查 CCM 和 kube-vip pods 是否已经启动:


kubectl get pods -n kube-system -w


kube-vip-dspacket-cloud-controller-manager 应该是 “Running”,并且没有出现错误。


配置额外的master server


既然我们的首个server已经启动并且正在运行,并且宣传它的EIP。我们可以使用它来加入我们其他的server,并且稍后我们的agent会使用该EIP。


这一点很重要,因为如果我们使用了其中一个服务器的IP,而这个服务器宕机了,agent将无法再与API server通信。  


k3sup join \  --ip $SERVER2 \  --server \  --server-ip $EIP \  --k3s-channel latest


  • --server 告诉K3s作为服务器加入集群。

  • --server-ip 注意我们指定的是EIP,而不是任何一台服务器的IP。


此命令会将kubeconfig文件写入本地目录,将其忽略,然后继续使用已合并到kubeconfig文件中的文件。


添加第三个服务器:


k3sup join \  --ip $SERVER3 \  --server \  --server-ip $EIP \  --k3s-channel latest


添加你的agents


要添加一个agent(或worker)节点,使用上面的join命令,但要删除--server标志。


agents=("$AGENT1" "$AGENT2")
for i in ${agents[*]} do k3sup join \ --ip $i \ --server \ --server-ip $EIP \ --k3s-channel latestdone


切换你的KUBECONFIG来使用EIP


在你自己的电脑上,将你的KUBECONFIG切换为使用EIP,而不是k3sup默认为你设置的SERVER1 IP。


编辑~/.kube/config并将IP $SERVER1替换为$EIP值。


在MacOS上进行的操作:


export EIP="147.75.100.237"export SERVER1="147.75.32.35"
sed -ie s/$SERVER1/$EIP/g ~/.kube/config


然后检查文件是否指向EIP:


cat ~/.kube/config |grep $EIP    server: https://147.75.100.237:6443


尝试在已安装新EIP的情况下使用kubectl


kubectl get nodes -o wide


部署工作负载


我们之前安装的arkade工具不仅可以安装CLI,而且是一个开源的Kubernetes marketplace。你可以在你的树莓派、Equinix Metal集群上甚至在你的笔记本电脑上使用它。它提供了大约 40 个 Kubernetes 应用程序,并且是开源的,因此您可以将其fork并添加自己的应用程序。


kube-vip 与 CCM 协同工作。CCM 将为您从 Equinix Metal 的 API 获取一个新的 IP 地址,然后将其分配给任何处于 Pending 状态的 LoadBalancer 服务,然后 kube-vip 开始为 IP 地址,并将流量路由到节点。


inlets-operator README中体现的是目前最快的例子:

https://github.com/inlets/inlets-operator


kubectl apply -f https://raw.githubusercontent.com/inlets/inlets-operator/master/contrib/nginx-sample-deployment.yamlkubectl expose deployment nginx-1 --port=80 --type=LoadBalancer


该IP在几秒之内就能够显示出来:


kubectl get svc -o wide -wNAME         TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE    SELECTORkubernetes   ClusterIP      10.43.0.1     <none>        443/TCP        151m   <none>nginx-1      LoadBalancer   10.43.71.39        80:30822/TCP   3s     app=nginxnginx-1      LoadBalancer   10.43.71.39        80:30822/TCP   5s     app=nginxnginx-1      LoadBalancer   10.43.71.39   147.75.80.22   80:30822/TCP   5s     app=nginx
NGINX_IP=$(kubectl get svc/nginx-1 -o jsonpath="{.spec.loadBalancerIP}")
curl -s http://$NGINX_IP | grep ""</span></span></code><code><span class="code-snippet_outer"><title>Welcome to nginx!
kubectl delete svc/nginx-1


要启动并运行Kubernetes仪表盘,只需运行:


arkade install kubernetes-dashboard


输出将告诉你如何获取一个token以及如何登录仪表盘。你可以通过输入以下命令在任意时间获取这一信息:


arkade info kubernetes-dashboard


在默认情况下,K3s内置的Traefik版本为1.x,你可以禁用或删除它然后安装你偏好的Ingress Controller:


kubectl delete svc/traefik -n kube-systemkubectl delete deploy/traefik -n kube-system


Arkade已经为IngressController提供了4个选项。你也可以运行arkade get helm,然后使用你喜欢的Helm chart:


arkade install ingress-nginx# Orarkade install traefik2# Orarkade install nginx-inc# Orarkade install kong-ingress


添加cert-manager:


arkade install cert-manager


你找到IngressController的IP地址之后,你可以为你可能创建的任意Ingress记录创建一个DNS记录,然后从LetsEncrypt免费获得TLS证书。


要安装带有加密TLS endpoint的OpenFaaS,请运行:


export DOMAIN=gateway.example.comarkade install openfaasarkade install openfaas-ingress \  --email webmaster@$DOMAIN \  --domain $DOMAIN


你需要使用IngressController的IP为gateway.example.com创建一个DNS A记录,然后你可以登录OpenFaaS或使用其URL打开浏览器:https://gateway.example.com


要托管一个Docker 镜像仓库,只需运行:


export DOMAIN=registry.example.comarkade install docker-registryarkade install docker-registry-ingress \  --email webmaster@$DOMAIN \  --domain $DOMAIN


要让域名工作,你只需要按照上面的registry.example.com创建DNS记录,并将其指向IngressController。


通过使用Ingress,你可以节省成本,也可以节省IP地址的费用,我在介绍中提到过,IP地址的费用大约是23元/月。


Linkerd和Istio也只是一个命令方式。


输入arkade install --help即可获得完整的列表。


总  结


在本教程中,我们展示了kube-vip在Equinix Metal的裸机云上使用时如何与BGP集成,以提供稳定的IP。


控制平面是高可用的,可以容忍至少一次故障,因为我们配置 K3s 使用其内置集群模式。内置集群模式使用和嵌入式的etcd版本来同步服务器。


6443端口的API server是高可用的,也可以容忍一次故障。这是因为API server的IP地址是EIP,由BGP提供。我们更新了我们的kubeconfig文件和我们的附加server和agent,使其集群的join命令使用EIP。


Cloud Controller Manager还使用BGP为您希望通过Kubernetes LoadBalancer公开的任何服务提供IP地址。


虽然这篇博文花了更长的时间来写,但它产生了一个高可用、快速以及生产就绪的工作负载的集群。


原文链接:

https://blog.alexellis.io/bare-metal-kubernetes-with-k3s/



推荐阅读

除了边缘场景,你还能在哪里使用K3s?

实践教程丨如何在边缘基础设施上运行故障预测解决方案?

1款开源工具,实现自动化升级K3S集群!



About k3s


k3s 是首个进入 CNCF 沙箱项目的 K8S 发行版,同时也是当前全球用户量最大的 CNCF 认证轻量级 K8S 发行版。自2019年3月发布以来,备受全球开发者们关注,至今GitHub Star数已超过 15,000,成为了开源社区最受欢迎的边缘计算 K8S 解决方案。截至目前,K3s全球下载量超过100万次,每周平均被安装超过2万次,其中30%的下载量来自中国。


k3s 专为在资源有限的环境中运行 Kubernetes 的研发和运维人员设计,将满足日益增长的在边缘计算环境中运行在 x86、ARM64 和 ARMv7 处理器上的小型、易于管理的 Kubernetes 集群需求。k3s 的发布,为开发者们提供了以“Rancher 2.X + k3s”为核心的从数据中心到云到边到端的 K8S 即服务(Kubernetes-as-a-Service),推动 Kubernetes Everywhere。

扫码添加k3s中文社区助手

加入官方中文技术社区

官网:https://k3s.io

浏览 165
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报