Categories
程式開發

輕量級Kubernetes k3s初探


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地址te​​st.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:

輕量級Kubernetes k3s初探 1

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:

輕量級Kubernetes k3s初探 2

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

輕量級Kubernetes k3s初探 3

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