超长干货!在裸机上配置高可用K3s,部署生产就绪工作负载
共 6201字,需浏览 13分钟
·
2020-12-27 12:51
作者简介
这篇教程是基于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 kubectl
arkade get k3sup
arkade get terraform
arkade get kubectx
根据这一步将这些二进制文件放到你的PATH:
# Add (k3sup) to your PATH variable
export 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 = 3
agents = 2
使用来自Equinix Metal仪表盘的值编辑api_token和project_id。在你的user profile上找到API key。
如果你希望更改节点规模,你可以编辑c1.small.x86并且使用一个不同的值。你可以在仪表盘上找到该选项。
现在运行terraform来创建主机:
terraform init
terraform plan -var-file=main.tfvars
terraform 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
尝试在集群中查询节点:
[get nodes ]$ kubectl
NAME STATUS ROLES AGE VERSION
k3s-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=lo
export EIP="147.75.100.237"
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.yaml apiVersion: v1
kind: Secret
metadata:
name: packet-cloud-config
namespace: kube-system
stringData:
cloud-sa.json: |
{
"apiKey": "$API_KEY",
"projectID": "$PROJECT_ID"
}
EOF
现在应用该secret,然后使用kube-vip修改CCM:
kubectl apply -f ./ccm-secret.yaml
kubectl 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-ds 和 packet-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 latest
done
切换你的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.yaml
kubectl expose deployment nginx-1 --port=80 --type=LoadBalancer
该IP在几秒之内就能够显示出来:
kubectl get svc -o wide -w
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 151m <none>
nginx-1 LoadBalancer 10.43.71.39
80:30822/TCP 3s app=nginx nginx-1 LoadBalancer 10.43.71.39
80:30822/TCP 5s app=nginx nginx-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 "
"
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-system
kubectl delete deploy/traefik -n kube-system
Arkade已经为IngressController提供了4个选项。你也可以运行arkade get helm,然后使用你喜欢的Helm chart:
arkade install ingress-nginx
# Or
arkade install traefik2
# Or
arkade install nginx-inc
# Or
arkade install kong-ingress
添加cert-manager:
arkade install cert-manager
你找到IngressController的IP地址之后,你可以为你可能创建的任意Ingress记录创建一个DNS记录,然后从LetsEncrypt免费获得TLS证书。
要安装带有加密TLS endpoint的OpenFaaS,请运行:
export DOMAIN=gateway.example.com
arkade install openfaas
arkade 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.com
arkade install docker-registry
arkade 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中文社区助手
加入官方中文技术社区
官网:https://k3s.io