Kubernetes: Kubernetes 工具

MetaLB

轻量级负载均衡(类型为 LoadBalancer 的服务)

https://metallb.universe.tf/

# 查看集群版本 1.37
root@master01:~# kubectl  get node
NAME                  STATUS   ROLES           AGE   VERSION
node01.jasper.org     Ready    worker          45h   v1.37.0
# 检查集群的代理模式。 nftables
root@master01:~# curl 127.0.0.1:10249/proxyMode
nftables

安装

# 2026.8 不再支持 ipvs ,所以不需要特殊处理
curl -L -o metallb-native.yaml \
     https://raw.githubusercontent.com/metallb/metallb/v0.16.1/config/manifests/metallb-native.yaml

## 或挂镜像下载
curl -L -o metallb-native.yaml \
     https://ghfast.top/https://raw.githubusercontent.com/metallb/metallb/v0.16.1/config/manifests/metallb-native.yaml

# 查看镜像版本
grep -E '^\s+image:' metallb-native.yaml

# 应用
kubectl apply -f metallb-native.yaml

# speaker 是 DaemonSet + hostNetwork: true
kubectl -n metallb-system get pod -o wid
# 网络信息
## node
root@master01:~# kubectl get nodes -o wide
NAME                  STATUS   ROLES           AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION             CONTAINER-RUNTIME
master01.jasper.org   Ready    control-plane   21h   v1.37.0   10.103.236.201   <none>        Ubuntu 26.04.1 LTS   7.0.0-31-generic (arm64)   containerd://2.3.5
master02.jasper.org   Ready    control-plane   20h   v1.37.0   10.103.236.202   <none>        Ubuntu 26.04.1 LTS   7.0.0-31-generic (arm64)   containerd://2.3.5
master03.jasper.org   Ready    control-plane   20h   v1.37.0   10.103.236.203   <none>        Ubuntu 26.04.1 LTS   7.0.0-31-generic (arm64)   containerd://2.3.5
node01.jasper.org     Ready    worker          46h   v1.37.0   10.103.236.204   <none>        Ubuntu 26.04.1 LTS   7.0.0-31-generic (arm64)   containerd://2.3.5
node02.jasper.org     Ready    worker          46h   v1.37.0   10.103.236.205   <none>        Ubuntu 26.04.1 LTS   7.0.0-31-generic (arm64)   containerd://2.3.5
node03.jasper.org     Ready    worker          22h   v1.37.0   10.103.236.206   <none>        Ubuntu 26.04.1 LTS   7.0.0-31-generic (arm64)   containerd://2.3.5

## service cidr
root@master01:~# grep -oE '\-\-service-cluster-ip-range=[^ ]*' /lib/systemd/system/kube-apiserver.service
--service-cluster-ip-range=192.168.0.0/16
## pod cidr
root@master01:~# kubectl get ippool -o custom-columns=NAME:.metadata.name,CIDR:.spec.cidr
NAME                  CIDR
default-ipv4-ippool   172.16.0.0/12
root@master01:~# kubectl get ippools.crd.projectcalico.org -o yaml | grep cidr
    cidr: 172.16.0.0/12

配置

# manifest 不含任何配置,装完两个组件会空转。先确认节点网段:
kubectl get nodes -o wide
ip -4 addr show | grep 10.103.236 # 掩码确认

# 找空闲地址
interface=enp2s0
for i in $(seq 240 250); do
  arping -c 2 -w 1 -I $interface 10.103.236.$i >/dev/null 2>&1 \
    && echo "10.103.236.$i 已被占用"
done

# 定义分配给负载均衡器服务的 IP
# 挑一段同网段、不在 DHCP 池里的空闲 IP
# 如节点在 10.103.236.0/24 段,就从这里划出闲置 ip
cat >ippool.yaml << EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default-pool
  namespace: metallb-system
spec:
  addresses:
  - 10.103.236.240-10.103.236.250
---
#二层转发功能
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - default-pool
EOF

kubectl apply -f ippool.yaml

# 查看
root@master01:~# kubectl  -n metallb-system  get ipaddresspool
NAME           AUTO ASSIGN   AVOID BUGGY IPS   ADDRESSES
default-pool   true          false             ["10.103.236.240-10.103.236.250"]

root@master01:~# kubectl  -n metallb-system  get ippools
NAME                  AGE
default-ipv4-ippool   41h
root@master01:~# kubectl  -n metallb-system  get l2advertisements
NAME         IPADDRESSPOOLS     IPADDRESSPOOL SELECTORS   INTERFACES
default-l2   ["default-pool"]

使用

cat > n.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer
EOF
  
kubectl  apply -f n.yaml


root@master01:~# kubectl  get svc
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      192.168.0.1      <none>           443/TCP        2d2h
nginx        LoadBalancer   192.168.21.226   10.103.236.240   80:30963/TCP   4s

虚拟节点

Kurl

kURL 是一个定制的 Kubernetes 发行版创建工具。自定义选择安装哪些组件。

https://kurl.sh/

#选择好,安装
curl https://kurl.sh/latest | sudo bash

镜像

  • configmap-reload 监听目录变化 docker pull ghcr.io/jimmidyson/configmap-reload:dev

集群管理

快速部署

部署工具

  • kubeadm 原生
    • kubekey
    • sealos
    • kubeaz
    • minikube
    • kind
    • kubespray
  • K0S
    • 近原生 k8s
  • Rancher
    • k3s
    • RKE2

kubekey

集群创建工具

# linux
KUBEKEY_VERSION=4.0.6
ARCH=$([ `arch`  = "aarch64" ] && echo arm64 || echo amd64)

wget https://github.com/kubesphere/kubekey/releases/download/v${KUBEKEY_VERSION}/kubekey-v${KUBEKEY_VERSION}-linux-${ARCH}.tar.gz

tar xf kubekey-v${KUBEKEY_VERSION}-linux-${ARCH}.tar.gz kk
# 1. 生成 inventory.yaml
./kk create inventory -o .
cat > inventory.yaml <<EOF
apiVersion: kubekey.kubesphere.io/v1
kind: Inventory
metadata:
  name: default
spec:
  hosts:
    localhost:
      connector:
        password: 123456      # 本地连接时这是 sudo 密码
  groups:
    k8s_cluster:
      groups:
        - kube_control_plane
        - kube_worker
    kube_control_plane:
      hosts:
        - localhost
    kube_worker:
      hosts:
        - localhost
    etcd:
      hosts:
        - localhost
EOF
# 如果你是 root 直接跑,connector 那段可以整个删掉——type 会根据节点名自动识别成 local。


# 2. 创建集群配置文件
./kk create config --with-kubernetes v1.37.0 -o .

# 按需修改
## kubernetes.kube_proxy.mode 只能选 ipvs 或 iptables,没有 nftables。
## KubeKey 默认 Pod 10.233.64.0/18、Service 10.233.0.0/18
vim config-v1.37.0.yaml
zone: "cn"                      # 关键,不然镜像还是走境外源

kubernetes:
  cluster_name: my-cluster
  control_plane_endpoint:
    host: lb.kubesphere.local
    type: local                 # 单节点保持 local,会往 /etc/hosts 写 127.0.0.1

cni:
  type: calico
  pod_cidr: 10.233.64.0/18      # 默认值
  service_cidr: 10.233.0.0/18   # 默认值

cri:
  # containerd 或 docker,默认 containerd


# 3 安装
./kk create cluster -i inventory.yaml -c config-v1.34.0.yaml

# 验证
kubectl get nodes

# 4. 删除集群
./kk delete cluster --all --with-data

k9s

命令行终端集群管理工具

# linux
K9S_VERSION=0.51.0
ARCH=$([ `arch`  = "aarch64" ] && echo arm64 || echo amd64)

wget https://github.com/derailed/k9s/releases/download/v${K9S_VERSION}/k9s_Linux_${ARCH}.tar.gz

tar xf k9s_Linux_${ARCH}.tar.gz  -C /usr/local/bin k9s

使用

k9s 的完整键位可以在程序内按 ? 查看帮助,按 ctrl-a 查看所有资源别名。

启动

k9s                          # 默认启动
k9s -n kube-system           # 指定命名空间
k9s --context jasper-org     # 指定集群 context
k9s --readonly               # 只读模式,禁用 delete/kill/edit
k9s info                     # 打印配置、日志、插件、别名文件的实际路径
k9s help                     # 所有 CLI 选项

导航

操作
打开资源视图 :pod⏎ (单数/复数/简称/别名都认)
指定命名空间 :pod kube-system⏎
直接带过滤 :pod /nginx⏎
直接带标签 :pod app=headlamp,env=prod⏎
切换集群 context :ctx⏎:ctx 集群名⏎
切换命名空间 :ns⏎ ,在列表里按 u 使用
返回上一层 esc
回到上一个命令(类似 cd -) -
命令历史前后翻 [ / ]
所有资源别名速查 ctrl-a
显示帮助 ?
退出 :q⏎ctrl-c

过滤和排序-这是找问题的核心区。

操作
正则过滤 /nginx⏎ ,支持 fred\vert{}blee
反向过滤 /! nginx⏎ 留下*不*匹配的
按标签过滤 /-l app=nginx⏎
模糊查找 /-f nginx⏎
只看故障/错误 ctrl-z
按状态排序 shift-s
按时间排序 shift-a
按名称排序 shift-n
按命名空间排序 shift-p (仅全命名空间视图下可用)
按当前列排序 shift-o
宽列(IP、节点等) ctrl-w
列左移 / 右移 shift-← / shift-→

ctrl-z 是运维最该记住的一个键。集群几百个 Pod,一键只留异常的, 比 kubectl get pod -A | grep -v Running 好用得多。

排查单个资源

操作
describe d
查看 YAML y
查看日志 l
上一次容器的日志 p
进容器 shell s
attach a
编辑 e
跳到 owner shift-j
刷新视图 ctrl-r
复制资源名 c
复制命名空间 n
  • p 看崩溃前的日志,等价于 kubectl logs --previous 。 CrashLoopBackOff 全靠它。
  • shift-j 从 Pod 一路跳到 ReplicaSet 再到 Deployment, 省掉翻 ownerReferences 的功夫。

日志视图内的键

操作
切换自动换行 w
切换时间戳 t
全屏 f

f 全屏同样适用于 YAML 和 Details 视图

找依赖关系

操作 适用对象
UsedBy — 谁在用这个 u ServiceAccount / PVC / Secret / ConfigMap
查看 ReplicaSets z Deployment 视图
Warp to namespace w 有命名空间列时

u 这个很多人不知道。"这个 Secret 能不能删"、"这个 PVC 挂在哪", 选中按 u 直接列出引用方。

日常操作

操作 适用对象
滚动重启 r Deployment / DaemonSet / StatefulSet
回滚 ctrl-l ReplicaSet 视图
手动触发 t CronJob
cordon / uncordon u Node 视图
drain r Node 视图
端口转发 shift-f Pod / Service / Container
查看已有转发 f 同上
压测(启动/停止) b Service / Port-forward

*警告*:=r= 在不同视图含义不同。工作负载视图是滚动重启, *Node 视图是 drain*。手滑代价差很远。

生产环境建议-默认开只读

k9s --readonly

或写进配置文件:

k9s:
  readOnly: true

多集群切换

# 1.在对方集群上执行,建一个专用 ServiceAccount
kubectl create sa k9s-ops -n kube-system
  kubectl create clusterrolebinding k9s-ops \
    --clusterrole=cluster-admin \
    --serviceaccount=kube-system:k9s-ops

## k8s 1.24 之后 SA 不再自动生成永久 Secret,
## kubectl create token 签出来的有期限,会过期。长期用要手动建:
  
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Secret
metadata:
  name: k9s-ops-token
  namespace: kube-system
  annotations:
    kubernetes.io/service-account.name: k9s-ops
type: kubernetes.io/service-account-token
EOF

## 然后组装 kubeconfig
SERVER=https://10.103.236.236:6443
CTX=prod-cluster
CA=$(kubectl -n kube-system get secret k9s-ops-token -o jsonpath='{.data.ca\.crt}')
TOKEN=$(kubectl -n kube-system get secret k9s-ops-token -o jsonpath='{.data.token}' | base64 -d)

cat > ./$CTX.kubeconfig <<EOF
apiVersion: v1
kind: Config
clusters:
- name: $CTX
  cluster:
    server: $SERVER
    certificate-authority-data: $CA
users:
- name: $CTX
  user:
    token: $TOKEN
contexts:
- name: $CTX
  context:
    cluster: $CTX
    user: $CTX
current-context: $CTX
EOF

# 2. 本地合并 kubeconfig
## 在合并前,先给对方的文件改名,避免冲突
## 确认 context 是不是叫 kubernetes-admin@kubernete
KUBECONFIG=./prod-cluster.kubeconfig kubectl config view --minify --raw

KUBECONFIG=./prod-cluster.kubeconfig kubectl config rename-context \
            kubernetes-admin@kubernetes prod-cluster


## 合并
cp ~/.kube/config ~/.kube/config.bak
KUBECONFIG=~/.kube/config:./prod-cluster.kubeconfig \
    kubectl config view --flatten > /tmp/merged

mv /tmp/merged ~/.kube/config
chmod 600 ~/.kube/config
# --flatten 是关键——它把证书文件的内容内嵌进去。
# 不加的话合并结果里只是 certificate-authority: /path/to/ca.crt
# 这种路径引用,换台机器就失效了。

# 验证
kubectl config get-contexts

k9s 里切换

  • 列出并切换 :ctx⏎
  • 直接切到指定集群:ctx prod-cluster⏎
  • 启动时指定:k9s –context prod-cluster
  • 用别的 kubeconfig 文件:k9s –kubeconfig /path/to/config
  • 跨集群看资源 :pod @prod-cluster⏎

k9s 每集群独立配置

$XDG_DATA_HOME/k9s/clusters/<集群名>/<context名>/config.yaml

k9s:
  cluster: prod-cluster
  readOnly: true          # 这个集群强制只读
  namespace:
    active: default
    lockFavorites: false
    favorites:
      - kube-system
      - headlamp
      - metallb-system
  view:
    active: po            # 进来默认落在 Pod 视图
  featureGates:
    nodeShell: true       # 允许在 Node 视图按 s 进宿主机