这几天把k8s折腾了个遍,个人觉得k3s更适合我,主要有五个优势
- 类似springboot的“约定优于配置”,就是默认给你一个开箱即用的东西,如果需要,再进行修改。而不是k8s那样样样要你配置
- 内置LoadBalancer实现,而不是像k8s那样没有LoadBalancer实现,导致裸机安装情况下得用NodePort、HostPort、HostNetwork来暴露服务,或者安装Metallb。
- 可以轻松的支持多云环境,对我这种有多个云厂商vps的玩家很友好
- 资源消耗较少。虽然节点增加后,控制面的内存压力也不小
- 文档docs.k3s.io很清晰。PS:不要看中文版的文档,也不要看rancher中国的文档,垃圾
环境说明
- linux发型版: RHEL9.2
- 关闭firewalld
- 关闭selinux
- 安装v1.27.3+k3s1版本k3s
- 安装v2.7.0版本kubernetes-dashboard
离线安装
步骤说明:
- 下载离线安装包
- 下载k3s可执行文件
- 下载install.sh安装脚本
- 进行安装
Tips:
- 关于离线安装,参考:Manually Deploy Images Method。下面的脚本通过wget和mv命令展示了如何准备各项资源来做离线安装
- 关于多云部署,参考Distributed hybrid or multicloud cluster。
- 多云部署需要预先安装wireguard的内核模块,RHEL9的5.14内核已经内置,老的发行版需要参考WireGuard Install Guide(k3s agent节点也需要安装wireguard内核模块)
- 执行安装脚本时,默认会把当前的http_proxy环境变量传递给kubectl、kubelet、containerd。我通过
CONTAINERD_
开头的环境变量配置了仅供containerd使用的而不影响kubectl、kubelet的本地clash代理,用于加速镜像拉取。不过这不是必须的,因为docker hub没有被墙。代理传递参考:Configuring an HTTP proxy。 --node-external-ip=<SERVER_EXTERNAL_IP> --flannel-backend=wireguard-native --flannel-external-ip
来设置server的使用外网ip,以实现多云集群--node-external-ip=<AGENT_EXTERNAL_IP>
来实现Agent使用外网ip,以实现多云集群。- 多云集群下,k3s的监管流量走外网的websocket,cluster流量走wireguard的VPN。我的集群是国内和国外机器都有,wireguard流量特征明显,不知道gfw会不会干扰wireguard流量
- 禁用traefik ingress controller。我觉得它用起来太烦了,而且还占用了80、443端口,不如直接用LoadBalancer
- 集群节点越多,对控制面节点的CPU、内存压力越大,参见requirements#cpu-and-memory
创建控制面Server节点
wget "https://github.com/k3s-io/k3s/releases/download/v1.27.3%2Bk3s1/k3s-airgap-images-amd64.tar" -O k3s-airgap-images-amd64.tar
sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo mv -f ./k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
wget "https://github.com/k3s-io/k3s/releases/download/v1.27.3%2Bk3s1/k3s" -O k3s
mv -f k3s /usr/local/bin/k3s
chmod +x /usr/local/bin/k3s
wget "https://get.k3s.io/" -O install.sh
chmod +x install.sh
. unpass #取消我的http_proxy环境变量
CONTAINERD_HTTP_PROXY=http://127.0.0.1:3128 \
CONTAINERD_HTTPS_PROXY=http://127.0.0.1:3128 \
CONTAINERD_NO_PROXY=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 \
K3S_TOKEN=12345 \
INSTALL_K3S_SKIP_DOWNLOAD=true \
./install.sh \
--node-external-ip="`curl https://bwg.arloor.dev:444/ip -k`" \
--flannel-backend=wireguard-native \
--flannel-external-ip \
--disable=traefik # 禁用traefik ingress controller
watch kubectl get pod -A
安装好server后,在server node上执行以下命令来得到agent加入集群的token:
cat /var/lib/rancher/k3s/server/token
Agent节点加入集群
. unpass
wget "http://cdn.arloor.com/k3s/k3s-airgap-images-amd64.tar" -O k3s-airgap-images-amd64.tar # https://github.com/k3s-io/k3s/releases/download/v1.27.3%2Bk3s1/k3s-airgap-images-amd64.tar
sudo mkdir -p /var/lib/rancher/k3s/agent/images/
sudo mv -f ./k3s-airgap-images-amd64.tar /var/lib/rancher/k3s/agent/images/
wget "http://cdn.arloor.com/k3s/k3s" -O k3s #https://github.com/k3s-io/k3s/releases/download/v1.27.3%2Bk3s1/k3s
mv -f k3s /usr/local/bin/k3s
chmod +x /usr/local/bin/k3s
wget "http://cdn.arloor.com/k3s/install.sh" -O install.sh #https://get.k3s.io/
chmod +x install.sh
# server上 cat /var/lib/rancher/k3s/server/token 的到token
K3S_TOKEN=K10098693af78777497406169383c59586da0916a6fc63bd293d9881f48b4789e0f::server:12345 \
INSTALL_K3S_SKIP_DOWNLOAD=true \
K3S_URL=https://118.25.142.222:6443 \
bash install.sh \
--node-external-ip="`curl https://bwg.arloor.dev:444/ip -k`"
如果Agent节点能自由访问Internet,也可以用下面的命令:
wget https://get.k3s.io/ -O install.sh \
&& chmod +x install.sh
INSTALL_K3S_VERSION=v1.27.3+k3s1 \
K3S_TOKEN=K10098693af78777497406169383c59586da0916a6fc63bd293d9881f48b4789e0f::server:12345 \
K3S_URL=https://118.25.142.222:6443 \
./install.sh \
--node-external-ip="`curl https://bwg.arloor.dev:444/ip -k`"
卸载Server和Agent
/usr/local/bin/k3s-uninstall.sh
/usr/local/bin/k3s-agent-uninstall.sh
另一个选择:使用Rancher的中国加速镜像安装
. unpass
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh -o install.sh
chmod +x install.sh
INSTALL_K3S_MIRROR=cn INSTALL_K3S_VERSION=v1.27.3+k3s1 K3S_TOKEN=12345 ./install.sh \
--node-external-ip="`curl https://bwg.arloor.dev:444/ip -k`" \
--flannel-backend=wireguard-native \
--flannel-external-ip \
--disable=traefik
watch kubectl get pod -A
虽然rancher中国的文档不咋样,但是这个加速镜像还是要点赞的, INSTALL_K3S_MIRROR=cn
环境变量就是来使用加速镜像的。此方式也不需要使用代理。我是在Rancher中国的安装选项介绍找到这个镜像的。建议配合 INSTALL_K3S_VERSION=v1.27.3+k3s1
环境变量指定k3s版本为v1.27.3+k3s1(我离线安装的版本)
测试dns正常工作
kubectl run curl --image=redhat/ubi9-minimal --attach --command --rm --restart=Never -- \
sh -c 'curl https://kubernetes.default:443 -k -v; echo $?'
参数 | 说明 |
---|---|
--attach |
附加到pod中 |
--command |
-- 后的表示命令,而不是参数 |
--rm |
运行完成后删除pod |
--restart=Never |
不设置的话,会是backoff的状态 |
kubernetes dashboard安装
先介绍两种安装方式,首先是通过manifest yaml文件安装,另一种是通过helm chart安装。再介绍token生成,以及使用token登陆kubernetes-dashboard。
使用manifest安装
这里还是使用v2.7.0版本,因为v3.0.0版本需要ingress-nginx-controller,而我不想用ingress-controller。
下载k8s dashboard的manifest,并预先下载镜像
. pass
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml -O recommended.yaml
. unpass
crictl pull docker.io/kubernetesui/dashboard:v2.7.0
crictl pull docker.io/kubernetesui/metrics-scraper:v1.0.8
修改Service/kubernetes-dashboard,将type设置成LoadBalancer,修改port为8443,修改后的样子:
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 8443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
type: LoadBalancer
创建工作负载
. unpass
kubectl apply -f recommended.yaml
watch kubectl get pod -n kubernetes-dashboard
使用helm安装
安装helm:
wget https://get.helm.sh/helm-v3.12.0-linux-amd64.tar.gz -O /tmp/helm-v3.12.0-linux-amd64.tar.gz
tar -zxvf /tmp/helm-v3.12.0-linux-amd64.tar.gz -C /tmp
mv /tmp/linux-amd64/helm /usr/local/bin/
安装dashboard的helm chart
需要先参考访问集群设置kubeconfig,从而让helm与集群交互
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm repo update
helm search repo kubernetes-dashboard -l #找到 app version 2.7.0对应的version为6.0.8
helm show values kubernetes-dashboard/kubernetes-dashboard --version 6.0.8 > /tmp/values.yaml
# 修改values.yaml
cat > /tmp/values.yaml <<EOF
service:
type: LoadBalancer
# Dashboard service port
externalPort: 8443
metricsScraper:
## Wether to enable dashboard-metrics-scraper
enabled: true
metrics-server:
enabled: false # k3s自带了metrics-server所以这里为false
args:
- --kubelet-insecure-tls # 必要
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=ExternalIP,InternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
EOF
kubectl create namespace kubernetes-dashboard
helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --version 6.0.8 \
-n kubernetes-dashboard \
-f /tmp/values.yaml
watch kubectl get pod -n kubernetes-dashboard
# 卸载
# helm delete kubernetes-dashboard --namespace kubernetes-dashboard
生成访问token
kubernetes-dashboard使用RBAC的权限控制,需要我们生成ServiceRole和ClusterRoleBinding,并生成token。可以生成永不过期的token,也可以生成带过期时间的token
永不过期的token
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: arloor
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: arloor
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: arloor
namespace: default
---
apiVersion: v1
kind: Secret
metadata:
name: arloor-secret
namespace: default
annotations:
kubernetes.io/service-account.name: arloor
type: kubernetes.io/service-account-token
EOF
kubectl get secret/arloor-secret -o yaml #查看token字段,base64格式的
kubectl describe secret/arloor-secret # 查看token字段,原始的
其中 kubectl get 得到的是Base64编码过的,需要base64解码才能使用:
base64 -d - <<EOF
xxxxxxx token
EOF
带过期时间的token
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: arloor
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: arloor
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: arloor
namespace: default
EOF
cat > /usr/local/bin/token <<\EOF
kubectl create token arloor --duration 24000h
EOF
chmod +x /usr/local/bin/token
token # 有效期100天
使用token登陆dashboard后可以看到类似下面的界面
kubernetes-dashboard的鉴权机制可以看access-control。我是用的文档中的Authorization header配合chrome的modHeader插件来使用上面的token进行鉴权,这样使用dashboard就很方便了。
k8s的RBAC鉴权机制可以参考Kubernetes(k8s)权限管理RBAC详解。简单说就是Role Based Access Control ,Role定义了访问一系列资源的权限。Subject有User、Group、ServiceAccount等几种。每个NameSpace都有一个默认ServiceAccount,名为"default"。Role和Subject(主体)通过RoleBinding绑定,绑定后Subject就有了Role定义的权限。ClusterRole有集群所有命名空间的权限,Role只有指定命名空间的权限。
访问集群
kubeconfig保存在 /etc/rancher/k3s/k3s.yaml。如果你安装了上游k8s的命令行工具,例如kubectl、helm,你需要给他们配置正确的kubeconfig位置。有三种方式,推荐方式三。
- 配置KUBECONFIG环境变量
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get pods --all-namespaces
helm ls --all-namespaces
- 增加
--kubeconfig
参数
kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get pods --all-namespaces
helm --kubeconfig /etc/rancher/k3s/k3s.yaml ls --all-namespaces
- 复制到默认kubeconfig的位置
cp -f /etc/rancher/k3s/k3s.yaml ~/.kube/config
Mac上管理该k3s集群:
mkdir ~/.kube
scp root@mi.arloor.com:/etc/rancher/k3s/k3s.yaml ~/.kube/config
curl -LO "https://dl.k8s.io/release/v1.27.3/bin/darwin/arm64/kubectl"
chmod +x kubectl
mv kubectl /data/bin/
sed -i "" 's/127.0.0.1/118.25.142.222/' ~/.kube/config
kubectl get nodes
其中,Mac上安装kubectl参考install-kubectl-binary-with-curl-on-macos。注意kubectl和集群版本要保持一致,否则有些api可能不兼容。
另外,使用sed命令是要注意: Mac 和 Linux 在 sed 命令的 -i 参数上存在一些不同。在 Linux 上,-i 参数后面可以直接跟着文件名,但在 macOS 上,-i 需要后跟一个扩展名。这个扩展名用于创建一个备份文件。如果你不想创建备份文件,你可以使用空字符串("")作为扩展名。
Server或Agent IP改变时的操作
下面以ServerIP变更为例:
Server
- 修改
/etc/systemd/system/k3s.service
中的--node-external-ip
参数 - 重启k3s服务
systemctl daemon-reload
systemctl restart k3s
Agent
sed -i 's/K3S_URL.*/K3S_URL="https:\/\/154.xx.xx.xx:6443"/' /etc/systemd/system/k3s-agent.service.env
systemctl restart k3s-agent.service