K3s Lightweight Kubernetes: Single-Node and HA Install - 夜莺博客

K3s Lightweight Kubernetes: Single-Node and HA Install

K3s packages the whole Kubernetes control plane — API server, scheduler,
controller-manager, kubelet, containerd and a datastore — into a single binary under 100 MB,
with sensible defaults and no etcd cuddling required. It is the right answer for edge sites,
lab clusters and small production workloads where a full upstream install is overkill. The
trade-off is that a lot of Kubernetes knowledge is implicit; this guide covers both the
one-command install and the production-shaped multi-server cluster with external datastore.

Single-Node Install

curl -sfL https://get.k3s.io | sh -

# Everything is one node, so kubectl already works
sudo k3s kubectl get node
sudo k3s kubectl get pods -A

# Use the normal kubectl client against it
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config
kubectl get nodes

A single-node K3s install is a fully functional cluster: all datastore, control-plane and
runtime components are present. What it is not is redundant. Anything with a service level
objective above "can be down for an hour" needs more nodes.

Useful Install Flags

curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=stable sh -s - \
  --node-name=k3s-edge-01 \
  --write-kubeconfig-mode=644 \
  --disable=traefik \
  --disable=servicelb \
  --node-ip=10.10.40.11 \
  --flannel-iface=eth1 \
  --kubelet-arg=max-pods=200
  • --disable=traefik — when you already run an ingress controller or a reverse
    proxy, the bundled one fights for ports 80/443.
  • --disable=servicelb — if you provide LoadBalancer addresses via MetalLB or your
    own BGP setup.
  • --flannel-iface — essential on hosts with multiple interfaces, which is most
    edge and lab hardware. Wrong interface selection is the number-one cause of "pods cannot reach
    each other".

Adding Agents

# From the server
sudo cat /var/lib/rancher/k3s/server/node-token

# On each agent
curl -sfL https://get.k3s.io | \
  K3S_URL=https://10.10.40.11:6443 \
  K3S_TOKEN=mynodetoken \
  sh -

# Verify
kubectl get nodes -o wide

Multi-Server HA With an External Datastore

Three servers with the embedded SQLite datastore is not a highly available control plane.
Two supported designs exist: embedded etcd (--cluster-init) on three or more
servers, or an external datastore (PostgreSQL, MySQL or etcd) with any number of server
nodes. The embedded etcd route is usually the simpler one.

# First server initialises the embedded etcd cluster
curl -sfL https://get.k3s.io | sh -s - server --cluster-init --node-ip=10.10.40.11

# Second and third servers join as additional control-plane members
curl -sfL https://get.k3s.io | sh -s - server \
  --server https://10.10.40.11:6443 \
  --token $(cat /var/lib/rancher/k3s/server/node-token)

# Confirm the datastore members
kubectl get nodes -l node-role.kubernetes.io/control-plane

With the external datastore model, point every server at the same database:

curl -sfL https://get.k3s.io | sh -s - server \
  --datastore-endpoint="postgres://k3s:pw@10.10.40.20:5432/k3s"

If you use PostgreSQL for this, size the connection pool deliberately — the API servers all
connect and each holds a pool; PgBouncer connection pooling for PostgreSQL is worth reading before you point three control planes at one database.

Storage

# K3s ships local-path-provisioner as the default StorageClass
kubectl get storageclass
kubectl patch storageclass local-path -p \
  '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

# A persistent volume claim works out of the box
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 10Gi
EOF

local-path binds a volume to one node. That is fine for a database with a
node affinity, and wrong for anything that must follow a pod around. If you need replication,
add Longhorn or an external CSI driver.

Operating a K3s Cluster

# Everything about the cluster in one place
kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl top nodes                # requires metrics-server, bundled

# K3s-specific
sudo systemctl status k3s
sudo journalctl -u k3s -n 100
sudo k3s check-config

# Upgrade deliberately
curl -sfL https://get.k3s.io | INSTALL_K3S_CHANNEL=v1.30 sh -
  • Upgrade one server at a time. The control plane tolerates a rolling upgrade; running the
    script on all three simultaneously does not.
  • Back up the datastore: for embedded etcd,
    k3s etcd-snapshot save; for an external datastore, back up the database like any
    other. Restoring a cluster without a snapshot is not possible.
  • Watch for the bundled components you did not ask for. The default Traefik and ServiceLB
    listeners are the usual reason port 80 is unexpectedly busy.
  • Deploy GitOps on top once the cluster is stable —
    Argo CD app-of-apps and sync waves covers the pattern, and Kubernetes CNI comparison helps if Flannel is not the right network plugin for your workloads.

原文链接:https://docs.k3s.io/quick-start