跳到主要内容

K3s 学习

K3s 是什么​

K3s 是由 Rancher Labs 发布的一款开源、极轻量的 Kubernetes 发行版,通过了CNCF一致性认证,适用于在资源有限的环境中运行 Kubernetes。

单节点的 K3S 架构​

20230505100848

1)k3s server 节点是运行 k3s server 命令的机器(裸机或者虚拟机),而 k3s Agent 节点是运行 k3s agent 命令的机器。

2)单点架构只有一个控制节点(在 K3s 里叫做 server node,相当于 K8s 的 master node),而且 K3s 的数据存储使用 sqlite 并内置在了控制节点上

3)在上图的这种配置中,每个 agent 节点都注册到同一个 server 节点。K3s 用户可以通过调用 server 节点上的 K3s API 来操作 Kubernetes 资源。

高可用的 K3S 架构​

虽然单节点 k3s 集群可以满足各种用例,但对于 Kubernetes control-plane 的正常运行至关重要的环境,可以在高可用配置中运行 K3s。一个高可用 K3s 集群由以下几个部分组成:

20230505101132

1)K3s Server 节点:两个或者更多的 server 节点将为 Kubernetes API 提供服务并运行其他 control-plane 服务

2)外部数据库:外部数据存储(与单节点 k3s 设置中使用的嵌入式 SQLite 数据存储相反)

安装服务​

# 后面的参数是为了让 kubectl 有权限访问
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

安装后可以检查一下版本号

20230505092259

# 这里其实也和 miniKube 一样,都是映射到别的命令来实现的
kubectl get pods -A

只不过 k3s 是通过 在 /usr/local/bin 中添加一个 kubectl 软链接到 k3s 的

20230505094713

可以通过 kubectl 查看 kube-system 运行的 pod 列表如下:

kubectl  get pod -n kube-system

20230505100634

可以发现并没有运行 apiserver、controller-manager、scheduler、kube-proxy 以及 flannel 等组件,因为这些都内嵌到了 k3s 进程。另外 k3s 已经给我们默认部署运行了 traefik ingress(反向代理插件)、metrics-server 等,不需要再额外安装了。

错误处理​

如果使用的时候报错

20230505092749

# 使用 root 用户执行这个命令
echo "K3S_KUBECONFIG_MODE=\"644\"" >> /etc/systemd/system/k3s.service.env

# 或者直接改权限
sudo chmod 644 /etc/rancher/k3s/k3s.yaml

如果发现下面这种连不上服务的情况,可能是服务没有启动,需要先启动服务

$ sudo systemctl restart k3s  
$ systemctl status k3s.service

20230505160436

检查 k3s 的错误日志: K3s 日志的位置将根据你运行 K3s 的方式和节点的操作系统而有所不同。

  • 从命令行运行时,日志将发送到 stdout 和 stderr。
  • 使用 openrc 运行时,将在 /var/log/k3s.log 中创建日志。
  • 使用 systemd 运行时,日志将发送到 Journald 并可以使用 sudo journalctl -f -n 100 -u k3s 查看​​。
  • Pod 日志在 /var/log/pods 中。
  • Containerd 日志在 /var/lib/rancher/k3s/agent/containerd/containerd.log 中。
# 如果是端口占用则可以通过下面的命令查看
sudo netstat -tlnp | grep 10250

Kubernetes 仪表板​

# https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# 注意粘贴到终端的时候要把,{ } 可能会被转义,导致命令执行失败
VERSION_KUBE_DASHBOARD=$(curl -w '%{url_effective}' -I -L -s -S https://github.com/kubernetes/dashboard/releases/latest -o /dev/null | sed -e 's|.*/||') && sudo k3s kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/${VERSION_KUBE_DASHBOARD}/aio/deploy/recommended.yaml

20230505102149

sudo kubectl get pod -n kubernetes-dashboard

20230505103524

配置仪表盘的访问权限

# dashboard.admin-user.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
# dashboard.admin-user-role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard

部署 admin-user 配置:

sudo kubectl create -f dashboard.admin-user.yml -f dashboard.admin-user-role.yml

创建完成后获取 secret 中 token 的值。

sudo kubectl -n kubernetes-dashboard create token admin-user 

20230505105500

要访问仪表板,必须为 K3s 集群创建一个安全通道:

# 默认是 8001
sudo kubectl proxy
# 如果想要指定端口
sudo kubectl proxy --port=8009

现在,可以通过以下网址访问仪表盘:

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

使用 admin-user 持有者令牌进行登录(把上面的 Token 粘贴进来)。

20230505105741

安装其它的 Agent 节点​

单节点 Server 安装是一个功能齐全的 Kubernetes 集群,它包括了托管工作负载 pod 所需的所有数据存储、control plane、kubelet 和容器运行时组件。除非你希望向集群添加容量或冗余,否则没有必要添加额外的 Server 或 Agent 节点。

TODO: 用到再添加负载

K3s on WSL 2​

我们不能直接使用 K3s 官网上推荐的用 curl 命令安装 K3s,因为 WSL2 没有 supervisor. 因此我们采用如下方式安装 K3s:

设置私有的 Docker 仓库​

K3s 为了降低资源消耗,将默认的 runtime 修改为 containerd,同时也内置了 Kubernetes CLI 工具 crictl 和 ctr。

K3s 默认的 containerd 配置文件目录为 /var/lib/rancher/k3s/agent/etc/containerd/config.toml,但直接操作 containerd 的配置文件去设置镜像仓库或加速器相比于操作 docker 要复杂许多。

K3s 为了简化配置 containerd 镜像仓库的复杂度,K3s 会在启动时检 /etc/rancher/k3s/ 中是否存在 registries.yaml 文件,如果存在该文件,就会根据 registries.yaml 的内容转换为 containerd 的配置并存储到 /var/lib/rancher/k3s/agent/etc/containerd/config.toml,从而降低了配置 containerd 镜像仓库的复杂度。

提示

如果想使用一个私有的镜像仓库,那么需要在每个使用镜像仓库的节点上以 root 身份创建这个文件。如果是 agent 节点可能没有 /etc/rancher/k3s/registries.yaml 这个文件,需要手动创建,然后改动方法和 server 节点一样

修改文件

sudo vim /etc/rancher/k3s/registries.yaml

K3s 镜像仓库配置文件由两大部分组成:mirrors 和 configs:

  • Mirrors 是一个用于定义专用镜像仓库的名称和 endpoint 的指令
  • Configs 部分定义了每个 mirror 的 TLS 和证书配置。对于每个 mirror,你可以定义auth和/或tls

containerd 使用了类似 K8S 中 svc 与 endpoint 的概念,svc 可以理解为访问名称,这个名称会解析到对应的 endpoint 上。

也可以理解 mirror 配置就是一个反向代理,它把客户端的请求代理到 endpoint 配置的后端镜像仓库。mirror 名称可以随意填写,但是必须符合IP或域名的定义规则。并且可以配置多个 endpoint,默认解析到第一个 endpoint,如果第一个 endpoint 没有返回数据,则自动切换到第二个 endpoint,以此类推。

比如以下配置示例:

mirrors:
"localhost:5000":
endpoint:
- "http://127.0.0.1:5000"
"alsritter.icu:5000":
endpoint:
- "http://127.0.0.1:5000"
"docker.io":
endpoint:
- "https://xxxxxxx.mirror.aliyuncs.com"
- "https://registry-1.docker.io"

可以通过 crictl pull 10.11.42.30:5000/library/alpine 和 crictl pull alsritter.icu:5000/library/alpine 获取到镜像,但镜像都是从同一个仓库获取到的。

配置非安全(http)私有仓库,只需要在 endpoint 中指定 http 协议头的地址即可。 在没有 TLS 通信的情况下,需要为 endpoints 指定 http://,否则将默认为 https。

可以看到 Containerd 配置文件末尾追加了如下配置:

sudo cat /var/lib/rancher/k3s/agent/etc/containerd/config.toml

20230505165004

如果你已经启动了 k3s,可以通过以下命令重启 k3s 并设置 Docker Registry 镜像仓库:

sudo systemctl restart k3s

检查是否可以访问到私有仓库

# 从私有仓库拉取镜像
sudo crictl pull localhost:5000/jokes:latest

IP 地址变更导致的错误​

先安装 etcdctl

ETCD_VERSION="v3.5.5"
ETCD_URL="https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz"
curl -sL ${ETCD_URL} | sudo tar -zxv --strip-components=1 -C /usr/local/bin
$ sudo ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' \
ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' \
ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt'\
ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' \
ETCDCTL_API=3 etcdctl member list

然后修改这个配置

$ sudo ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' \
ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' \
ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' \
ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' \
ETCDCTL_API=3 etcdctl member update b273bc7741bcb020 \
--peer-urls="https://192.168.2.55:2379"

检查服务日志​

可以通过以下方式去检查为啥服务没有起来

1、使用 kubectl describe deployment 命令查看 Deployment 的详细信息,包括 Pod 的创建状态、事件和各个容器的状态:

kubectl describe deployment <deployment-name>

20230505150917

2、使用 kubectl get pods 命令查看 Pod 的状态,包括 Pod 是否已经创建和正在运行的容器:

kubectl get pods

如果 Pod 处于 Pending 状态,可能是因为调度器无法找到合适的节点来运行 Pod。可以使用 kubectl describe pod 命令查看 Pod 的详细信息,包括 Pod 调度的状态和调度器的事件:

kubectl describe pod <pod-name>

20230505151307

3、使用 kubectl logs 命令查看容器的日志,以查找容器启动失败的原因:

kubectl logs <pod-name> <container-name>

如果容器未能启动,可能是由于容器映像中缺少必要的文件或配置,或者容器启动时发生错误。在容器日志中查找错误消息和异常堆栈跟踪,可以帮助你确定容器启动失败的原因。

4、最后,可以查看 Kubernetes 控制面板的事件日志,以查找与 Deployment 相关的事件和错误:

kubectl get events

这些事件可能包括 Pod 调度失败、容器启动失败等等。通过查看事件日志,可以快速定位 Deployment 未启动的原因。

复制 config 文件​

sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config

使用 kubectl 生成 .kube/config 文件​

Kubernetes 的 .kube/config 文件包含了访问 Kubernetes 集群所需的所有信息,包括集群、用户、命名空间和身份验证信息。这个文件通常在你设置或修改集群配置时自动创建和更新,但有时你可能需要手动创建或编辑它。

1、设置集群: 你需要有一个 Kubernetes 集群,并且知道它的 API server 地址。

kubectl config set-cluster <cluster-name> --server=https://<api-server-url> --insecure-skip-tls-verify

k3s 默认会在 /etc/rancher/k3s/k3s.yaml 路径下生成一个 kubeconfig 文件。可以查看这个文件来找到 API server 的地址

或者直接用命令

kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'

2、设置证书: 如果你的集群使用了 TLS,你需要将客户端证书、客户端密钥和 CA 证书添加到配置中。

kubectl config set-credentials <user-name> --client-certificate=/path/to/client-certificate.crt --client-key=/path/to/client-key.key
kubectl config set-context <context-name> --cluster=<cluster-name> --user=<user-name>

3、设置上下文: 上下文是集群、用户和命名空间的组合。

kubectl config set-context <context-name> --cluster=<cluster-name> --user=<user-name> --namespace=<namespace>

4、使用上下文: 选择一个上下文作为当前上下文。

kubectl config use-context <context-name>

以上命令会在 ~/.kube/config 文件中生成相应的配置。你可以通过编辑这个文件来进一步调整配置。

手动创建 .kube/config 文件​

你也可以直接手动创建或编辑 ~/.kube/config 文件。以下是一个示例配置文件的内容:

apiVersion: v1
clusters:
- cluster:
certificate-authority: /path/to/ca.crt
server: https://<api-server-url>
name: <cluster-name>
contexts:
- context:
cluster: <cluster-name>
namespace: <namespace>
user: <user-name>
name: <context-name>
current-context: <context-name>
kind: Config
preferences: {}
users:
- name: <user-name>
user:
client-certificate: /path/to/client.crt
client-key: /path/to/client.key

这个文件包含了连接到 Kubernetes 集群所需的所有信息。你需要将 <cluster-name>, <api-server-url>, <user-name>, <namespace>, <context-name>, /path/to/ca.crt, /path/to/client.crt, 和 /path/to/client.key 替换为实际的值。

注意:如果你的 Kubernetes 集群使用了某些特殊的身份验证方法(如 GKE 的 gcloud 或 AWS 的 aws-cli),你可能需要通过它们特定的命令行工具来获取或更新你的 Kubernetes 配置文件。

Reference​