轻量级Kubernetes k3s初探

标签: 轻量级 kubernetes k3s | 发表时间:2020-04-12 14:13 | 作者:付广平
出处:https://www.infoq.cn

1 k3s简介–5 less than K8s

k3s [1] 是rancher®开源的一个Kubernetes发行版,从名字上就可以看出k3s相对k8s做了很多裁剪和优化,二进制程序不足50MB,占用资源更少,只需要512MB内存即可运行。

而之所以称为k3s是因为相对k8s裁剪了如下5个部分:

  • 过时的功能和非默认功能
  • Alpha功能
  • 内置的云提供商插件
  • 内置的存储驱动
  • Docker

官方称k3s是:

★ k3s是史上最轻量级Kubernetes.”

相对k8s最主要的优化如下:

  • 使用内嵌轻量级数据库SQLite作为默认数据存储替代etcd,当然etcd仍然是支持的。
  • 内置了local storage provider、service load balancer、helm controller、Traefik ingress controller,开箱即用。
  • 所有Kubernetes控制平面组件如api-server、scheduler等封装成为一个精简二进制程序,控制平面只需要一个进程即可运行。
  • 删除内置插件(比如cloudprovider插件和存储插件)。
  • 减少外部依赖,操作系统只需要安装较新的内核以及支持cgroup即可,k3s安装包已经包含了containerd、Flannel、CoreDNS,非常方便地一键式安装,不需要额外安装Docker、Flannel等组件。

k3s的四大使用场景为:

  • Edge
  • IoT
  • CI
  • ARM

当然如果想学习k8s,而又不想折腾k8s的繁琐安装部署,完全可以使用k3s代替k8s,k3s包含了k8s的所有基础功能,而k8s附加功能其实大多数情况也用不到。

2 一键式安装k3s

k3s安装确实非常简单,只需要一个命令即可完成:

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

通过如上只执行了一个命令即部署了一套all in one k3s单节点环境,相对k8s无需额外安装如下组件:

  • kubelet
  • kube-proxy
  • Docker
  • etcd
  • ingress,如ngnix

当然可以使用k3s agent添加更多的worker node,只需要添加 K3S_URLK3S_TOKEN参数即可,其中 K3S_URL为api-server URL,而 k3S_TOKEN为node注册token,保存在master节点的 /var/lib/rancher/k3s/server/node-token路径。

3 和使用k8s一样使用k3s

3.1 和使用k8s一样使用k3s命令工具

k3s内置了一个kubectl命令行工具,通过 k3s kubectl调用,为了与k8s的kubectl命令一致,可以设置alias别名:

  
# 该步骤可以省略,在/usr/local/bin中已经添加了一个kubectl软链接到k3s
alias kubectl='k3s kubectl`

# 配置kubectl命令补全
source <(kubectl completion bash)

配置完后,我们就可以通过 kubectl查看kube-system运行的pod列表如下:

  
# kubectl  get pod -n kube-system
NAME                                      READY   STATUS      RESTARTS   AGE
metrics-server-6d684c7b5-4qppl            1/1     Running     0          70m
local-path-provisioner-58fb86bdfd-8l4hn   1/1     Running     0          70m
helm-install-traefik-pltbs                0/1     Completed   0          70m
coredns-6c6bb68b64-b9qcl                  1/1     Running     0          70m
svclb-traefik-2ttg2                       2/2     Running     0          70m
traefik-7b8b884c8-xkm77                   1/1     Running     0          70m

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

k3s默认没有使用Docker作为容器运行环境,而是使用了内置的contained,可以使用 crictl子命令与CRI交互。

当然如果习惯使用docker命令行可以设置如下别名:

  alias docker='k3s crictl'

# 配置docker命令补全
source <(docker completion)
complete -F _cli_bash_autocomplete docker

通过 docker ps查看运行的容器:

  
# docker  ps
CONTAINER           IMAGE               CREATED             STATE               NAME                     ATTEMPT             POD ID
deedde06105b5       8fafd8af70e9a       6 minutes ago       Running             kubernetes-bootcamp-v1   0                   b59bdf9ed7b2a
5464873f8064a       8fafd8af70e9a       6 minutes ago       Running             kubernetes-bootcamp-v1   0                   51d2058a38262
d8ae5df73ee95       aa764f7db3051       About an hour ago   Running             traefik                  0                   a7990965f71c3
1ecdf0ce98ebf       897ce3c5fc8ff       About an hour ago   Running             lb-port-443              0                   4057796b8eddd
021a4d7bcc391       897ce3c5fc8ff       About an hour ago   Running             lb-port-80               0                   4057796b8eddd
089ee47dd3de0       c4d3d16fe508b       About an hour ago   Running             coredns                  0                   5e54975c3ae1e
3c97b40b9beed       9d12f9848b99f       About an hour ago   Running             local-path-provisioner   0                   5a4e666f9c8f7
ac020ab1621c0       9dd718864ce61       About an hour ago   Running             metrics-server           0                   f69f6812b7a66

当然我们只是使用 crictl模拟了 docker命令,相对真正的 docker我们发现多了 ATTEMPT以及 POD ID,这是CRI所特有的。

3.2 和使用k8s一样创建k3s资源

我们使用k8s最喜欢拿来入门的 bootcamp作为例子,Deployment声明如下:

  apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: kubernetes-bootcamp-v1
  name: kubernetes-bootcamp-v1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: kubernetes-bootcamp-v1
  template:
    metadata:
      labels:
        app: kubernetes-bootcamp-v1
    spec:
      containers:
      - image: jocatalin/kubernetes-bootcamp:v1
        name: kubernetes-bootcamp-v1

使用 kubectl apply创建Deployment资源:

  # kubectl  apply -f kubernetes-bootcamp-v1.yaml
deployment.apps/kubernetes-bootcamp-v1 created
# kubectl  get pod
NAME                                     READY   STATUS        RESTARTS   AGE
kubernetes-bootcamp-v1-c5ccf9784-m79vt   1/1     Running       0          3s
kubernetes-bootcamp-v1-c5ccf9784-5blct   1/1     Running       0          3s

创建Service:

  # kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    app: kubernetes-bootcamp-v1
  name: kubernetes-bootcamp-v1
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: kubernetes-bootcamp-v1
  type: ClusterIP
# kubectl  get service
NAME                     TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes               ClusterIP   10.43.0.1              443/TCP    29m
kubernetes-bootcamp-v1   ClusterIP   10.43.132.97           8080/TCP   8m14s
# curl 10.43.132.97:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-v1-c5ccf9784-5blct | v=1

我们不需要再单独安装其他ingress controller,因为k3s已经内置了Traefik,直接创建Ingress:

  # kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "int32bit-test-ingress"
  labels:
    app: int32bit-test-ingress
spec:
  rules:
    - host: test.int32bit.me
      http:
        paths:
        - path: /v1
          backend:
            serviceName: "kubernetes-bootcamp-v1"
            servicePort: 8080
# kubectl  get ingress int32bit-test-ingress
NAME                    HOSTS              ADDRESS           PORTS   AGE
int32bit-test-ingress   test.int32bit.me   192.168.193.197   80      5m54s

其中 192.168.193.197为master节点的IP,由于我们没有DNS解析,因此可以通过配置 /etc/hosts文件进行静态配置:

  192.168.193.197 test.int32bit.me

此时我们就可以直接通过ingress地址test.int32bit.me访问我们的服务了,ingress直接通过 ClusterIP转发,不需要 NodePort

  # curl http://test.int32bit.me/v1
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-v1-c5ccf9784-5blct | v=1

我们发现k3s和k8s的Resource声明完全兼容,没有任何区别。

4 k3s网络

4.1 CNI网络

k3s内置了Flannel网络插件,默认使用VXLAN后端,默认IP段为 10.42.0.0/16

  # ip -o -d link show flannel.1
14: flannel.1:  mtu 8951 \
    qdisc noqueue state UNKNOWN mode DEFAULT group default \
    link/ether 46:61:15:1f:1e:3f brd ff:ff:ff:ff:ff:ff promiscuity 0 \
    vxlan id 1 local 192.168.193.197 dev ens5 \
    srcport 0 0 dstport 8472 nolearning ttl inherit ageing 300 \
    udpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 \
    numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

内置的Flannel除了VXLAN还支持ipsec、host-gw以及wireguard。

当然除了默认的Flannel,k3s还支持其他CNI,如Canal、Calico等。

4.2 其他网络组件

k3s除了内置Flannel网络插件以外,还内置了CoreDNS、Traefik Ingress Controller、Service Load Balancer,如果不使用默认的组件,用户也可以自己部署其他组件,比如使用MetalLB替代内置的load balancer。

5 k3s存储

5.1 内置本地存储插件

k3s删除了k8s内置cloud provider以及storage插件(当然这不会影响使用通过手动安装的外部插件),内置了Local Path Provider。

比如我们创建一个2G的PVC:

  # kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-path-pvc
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 2Gi

创建一个Pod使用新创建的PVC:

  # kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: volume-test
    image: jocatalin/kubernetes-bootcamp:v1
    volumeMounts:
    - name: volv
      mountPath: /data
  volumes:
  - name: volv
    persistentVolumeClaim:
      claimName: local-path-pvc

查看创建的Pod以及PVC:

  # kubectl get pod volume-test
NAME          READY   STATUS    RESTARTS   AGE
volume-test   1/1     Running   0          116s
# kubectl get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
local-path-pvc   Bound    pvc-6bd15859-540f-4ade-94dc-821e29cacdba   2Gi        RWO            local-path     4m8s
# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
pvc-6bd15859-540f-4ade-94dc-821e29cacdba   2Gi        RWO            Delete           Bound    default/local-path-pvc   local-path              106s

查看PV:

  # kubectl describe  pv
Name:              pvc-6bd15859-540f-4ade-94dc-821e29cacdba
Labels:            
Annotations:       pv.kubernetes.io/provisioned-by: rancher.io/local-path
Finalizers:        [kubernetes.io/pv-protection]
StorageClass:      local-path
Status:            Bound
Claim:             default/local-path-pvc
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          2Gi
Node Affinity:
  Required Terms:
    Term 0:        kubernetes.io/hostname in [ip-192-168-193-197]
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/rancher/k3s/storage/pvc-6bd15859-540f-4ade-94dc-821e29cacdba
    HostPathType:  DirectoryOrCreate
Events:            

可见其实就类似k8s的HostPath存储卷类型。

5.2 使用外部存储Longhorn

前面提到的内置local path存储,只能单机使用,不支持跨主机使用,也不支持存储的高可用。

可以通过使用外部的存储插件解决k3s存储问题,比如 Longhorn [2]

Longhorn是专门针对Kubernetes设计开发的云原生分布式块存储系统,可以直接使用 kubectl apply或者 helm安装:

  kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/longhorn.yaml

为了能够访问Longhorn Dashboard,我创建如下ingress:

  apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "longhorn-ui"
  namespace: longhorn-system
  labels:
    app: longhorn-ui
spec:
  rules:
    - host: longhorn-frontend.int32bit.me
      http:
        paths:
        - path: /
          backend:
            serviceName: "longhorn-frontend"
            servicePort: 80
    - host: longhorn-backend.int32bit.me
      http:
        paths:
        - path: /
          backend:
            serviceName: "longhorn-backend"
            servicePort: 9500

通过 http://longhorn-frontend.int32bit.me/dashboard即可访问Dashboard:

longhorn

安装Longhorn storageclass:

  kubectl create -f \
https://raw.githubusercontent.com/longhorn/longhorn/master/examples/storageclass.yaml

创建PVC:

  # kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-volv-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 2Gi

创建Pod使用新创建的PVC:

  # kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: test-volume-longhorn
spec:
  containers:
  - name: test-volume-longhorn
    image: jocatalin/kubernetes-bootcamp:v1
    volumeMounts:
    - name: volv
      mountPath: /data
  volumes:
  - name: volv
    persistentVolumeClaim:
      claimName: longhorn-volv-pvc

通过Longhorn Dashboard查看volume:

longhorn-pvc

可见PV已经挂载到Pod test-volume-longhorn中。

6 加上k9s,全了

最后,附上k9s,这样k3s、k8s、k9s 全了 : )

  https://github.com/derailed/k9s/releases/download/v0.19.0/k9s_Linux_x86_64.tar.gz
tar xvzf k9s_Linux_x86_64.tar.gz
mv k9s /usr/local/bin/kubectl-k9s

k9s

写在最后

k3s在去年的2月就已经推出并开源,现在不算是新东西,周末正好没啥事于是安装体验下,主要还是想使用下 mdnice [3] 体验下公众号文章排版效果。

使用后一次后发现,mdnice真的是特别适合技术类公众号文章编辑:

  • Markdown语法,支持在线编辑,写完后即排版成功,复制即可粘贴到微信公众号;
  • 支持零配置图床、脚注、代码、公式;
  • 内置18种风格主题,支持自定义CSS样式;
  • 内容在浏览器中实时保存;
  • 支持chrome插件,可直接在微信公众平台上编辑。

尤其是代码块,代码高亮和滚屏是刚需。目前很多公众号编辑器支持得都不是很好,比如秀米就对代码块的支持效果非常不好。而midnice直接使用Markdown语法嵌入代码块,并且支持Atom、Monokai、github、vs2015、xcode等多种代码风格。

参考资料

[1] k3s: https://rancher.com/docs/k3s/latest/en/

[2] Longhorn: https://github.com/longhorn/longhorn

[3] mdnice: https://docs.mdnice.com/#/

本文转载自公众号int32bit(ID:int32bit)。

原文链接

https://mp.weixin.qq.com/s/gtw6k-jmtatlk8LSkMzGiA

相关 [轻量级 kubernetes k3s] 推荐:

轻量级Kubernetes k3s初探

- - InfoQ推荐
1 k3s简介–5 less than K8s. k3s [1] 是rancher®开源的一个Kubernetes发行版,从名字上就可以看出k3s相对k8s做了很多裁剪和优化,二进制程序不足50MB,占用资源更少,只需要512MB内存即可运行. 而之所以称为k3s是因为相对k8s裁剪了如下5个部分:.

轻量级 Kubernetes 多租户方案的探索与实践

- - IT瘾-dev
作者:任静思,火山引擎云原生工程师. 本文整理自火山引擎开发者社区 Meetup 第八期演讲,主要介绍了字节跳动轻量级 Kubernetes 多租户方案 KubeZoo 的适用场景和实现原理. Kubernetes多租户模型. 伴随着云原生技术的发展和推广,Kubernetes 已经成为了云计算时代的操作系统.

Kubernetes & Microservice

- - 午夜咖啡
这是前一段时间在一个微服务的 meetup 上的分享,整理成文章发布出来. 谈微服务之前,先澄清一下概念. 微服务这个词的准确定义很难,不同的人有不同的人的看法. 比如一个朋友是『微服务原教旨主义者』,坚持微服务一定是无状态的 http API 服务,其他的都是『邪魔歪道』,它和 SOA,RPC,分布式系统之间有明显的分界.

Kubernetes学习(Kubernetes踩坑记)

- - Z.S.K.'s Records
记录在使用Kubernetes中遇到的各种问题及解决方案, 好记性不如烂笔头. prometheus提示 /metrics/resource/v1alpha1 404. 原因: 这是因为[/metrics/resource/v1alpha1]是在v1.14中才新增的特性,而当前kubelet版本为1.13.

kubernetes移除Docker?

- -
两周前,Kubernetes在其最新的Changelog中宣布1.20之后将要弃用dockershime,也就说Kubernetes将不再使用Docker做为其容器运行时. 这一消息持续发酵,掀起了不小的波澜,毕竟Kubernetes+Docker的经典组合是被市场所认可的,大量企业都在使用. 看上去这个“弃用”的决定有点无厘头,那么为什么Kubernetes会做出这样的决定.

Kubernetes 完全教程

- - 午夜咖啡
经过一个阶段的准备,视频版本的 《Kubernetes 完全教程》出炉了. 课程一共分为七节,另外有一节 Docker 预备课,每节课大约一个多小时. 目标是让从没接触过 Kubernetes 的同学也能通过这个课程掌握 Kubernetes. 为什么要学习 Kubernetes. 在介绍课程之前,先说说为什么要学习 Kubernetes 以及什么人需要学习 Kubernetes.

Kubernetes 监控详解

- - DockOne.io
【编者的话】监控 Kubernetes 并不是件容易的事. 本文介绍了监控 Kubernetes 的难点、用例以及有关工具,希望可以帮助大家进一步了解监控 Kubernetes. 如果想要监控 Kubernetes,包括基础架构平台和正在运行的工作负载,传统的监控工具和流程可能还不够用. 就目前而言,监控 Kubernetes 并不是件容易的事.

Kubernetes 切换到 Containerd

- - bleem
由于 Kubernetes 新版本 Service 实现切换到 IPVS,所以需要确保内核加载了 IPVS modules;以下命令将设置系统启动自动加载 IPVS 相关模块,执行完成后需要重启. 重启完成后务必检查相关 module 加载以及内核参数设置:. 1.2、安装 Containerd. Containerd 在 Ubuntu 20 中已经在默认官方仓库中包含,所以只需要 apt 安装即可:.

Spring Cloud Kubernetes指南

- -
当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件. 但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性.

喜大普奔:Spark on kubernetes

- - Zlatan Eevee
两个星期前(08/15/2017),spark社区提了一个新的SPIP(Spark Project Improvement Proposals): Spark on Kubernetes: Kubernetes as A Native Cluster Manager,即用k8s管理spark集群. 经过社区2个星期的投票,看上去很快要能合入了.