久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Kubernetes容器隔離問題實例分析

142次閱讀
沒有評論

共計 6337 個字符,預計需要花費 16 分鐘才能閱讀完成。

這篇文章主要講解了“Kubernetes 容器隔離問題實例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學習“Kubernetes 容器隔離問題實例分析”吧!

背景

容器中看到的 /proc 偽文件系統的信息是宿主的 /proc,沒有隔離 /proc 意味著獲取不到容器中進程相關的 proc 信息。另外,一些需要讀取 proc 信息的應用,會獲取到錯誤的數據。/proc/meminfo,/proc/cpuinfo, /proc/stat, /proc/uptime, /proc/loadavg 等

用戶 UID/GID 的映射, 導致容器中的進程具有宿主上相同 uid/gid 用戶的權限

需求分析方案調研

Docker 社區里有討論過類似的問題,https://github.com/docker/docker/issues/8427,可以通過 kernel patch 或者 bind mount /proc  來實現。 
淘寶團隊在幾年前曾經發過一個 kernel patch 
https://github.com/alibaba/taobao-kernel/blob/master/patches.taobao/overlayfs-0005-vfs-introduce-clone_private_mount.patch

業界討論主要有以下幾種方案:

##  方案一、-  直接修改 proc 文件系統  
- https://lkml.org/lkml/2012/5/28/299
- mount -t proc -o meminfo-from-cgroup none /path/to/container/proc
缺點:不可能要求并入內核

缺點:不是一個廣泛接受的方案,不說自己修改命令可能產生的 bug  和成本。不同的 linux 版本,可能會需要不同的補丁。

解決方案

為 LXC 準備的 FUSE 文件系統, 提供了如下的特性:

* a cgroupfs compatible view for unprivileged containers
* a set of cgroup-aware files:
 * cpuinfo
 * meminfo
 * stat
 * uptime

用戶空間文件系統 (Filesystem in Userspace, FUSE)

用戶空間文件系統 是操作系統中的概念,指完全在用戶態實現的文件系統。

目前 Linux 通過內核模塊對此進行支持。一些文件系統如 ZFS,glusterfs 使用 FUSE 實現。

FUSE 的工作原理如上圖所示。假設基于 FUSE 的用戶態文件系統 hello 掛載在 /tmp/fuse 目錄下。當應用層程序要訪問 /tmp/fuse 下的文件時,通過 glibc 中的函數進行系統調用,處理這些系統調用的 VFS 中的函數會調用 FUSE 在內核中的文件系統;內核中的 FUSE 文件系統將用戶的請求,發送給用戶態文件系統 hello;用戶態文件系統收到請求后,進行處理,將結果返回給內核中的 FUSE 文件系統;最后,內核中的 FUSE 文件系統將數據返回給用戶態程序。

Linux 內核從 2.6.14 支持通過 FUSE 模塊

在用戶空間實現文件系統

libfuse: 用戶空間的 fuse 庫, 非特權用戶可訪問。

LXCFS – 基于 FUSE 實現的用戶空間文件系統

站在文件系統的角度: 通過調用 libfuse 庫和 內核的 FUSE 模塊交互實現

兩個基本功能

讓每個容器有自身的 cgroup 文件系統視圖, 類似 Cgroup Namespace

提供容器內部虛擬的 proc 文件系統

LXCFS 視角

從 main 函數可以看出, 初始化的過程包括:

將運行時工作目錄 /run/lxcfs/controllers/ 掛載到 tmpfs 文件系統

將當前系統的各個 group 子系統重新掛載到 /run/lxcfs/controllers/ 目錄

調用 libfuse 庫的主函數 fuse_main(), 指定用戶態文件系統的目標目錄 - /var/lib/lxcfs/

使用 struct fuse_operations 的 ops 方法, 與內核中的 FUSE 模塊交互。lxcfs.c:701

容器視角

把虛擬 proc 文件系統掛載到 docker 容器

用戶在容器中讀取 /proc/meminfo ,cpuinfo 等信息

在 proc_meminfo_read 操作中實現 讀取 meminfo

過程: 拿到 meminfo 進程的 pid 傳給 lxcfs — 拿到 pid 的 cgroup 分組 — host 的 /cgroup 目錄對應進程的 cgroup 子系統信息

存在的問題以及如何解決

LXCFS 的部署問題以及帶來的影響和成本?見如下補充的 LxcFS – k8s 實踐

故障恢復,如何自動 remount?如果 lxcfs 進程重啟了,那么容器里的 /proc/cpuinfo 等等都會報 transport connected failed 這個是因為 /var/lib/lxcfs 會刪除再重建,inode 變了。所以參考豆瓣的做法,共享 mount 事件,重新給容器掛載

https://github.com/lxc/lxcfs/issues/193

https://github.com/alibaba/pouch/issues/140

User Namespace

解決什么問題?

用戶 UID/GID 的映射, 導致容器中的進程具有宿主上相同 uid/gid 用戶的權限

docker 從 1.10 版本 開始支持 user namespace 隔離。使用參數:DOCKER_OPTS= –userns-remap=default

相關文檔鏈接:

基于 LXCFS 增強 docker 容器隔離性的分析 2015.12.9

docker 容器顯示問題及修復 2017-03-23

lxc-1.0.9 lxcfs-2.0.0 fuse-2.8.7 源碼詳細注釋分析

Kubernetes 之路 2 – 利用 LXCFS 提升容器資源可見性

Kubernetes Initializers

看看大阿里 pouch 怎么解決 remount 這個問題

lxcfs 的 Kubernetes 實踐

注:以下內容來自文檔鏈接 4,內容有稍作修改

首先我們要在集群節點上安裝并啟動 lxcfs,我們將用 Kubernetes 的方式,用利用容器和 DaemonSet 方式來運行 lxcfs FUSE 文件系統。

本文所有示例代碼可以通過以下地址從 Github 上獲得

git clone https://github.com/denverdino/lxcfs-initializer
cd lxcfs-initializer

其 manifest 文件如下

apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
 name: lxcfs
 labels:
 app: lxcfs
spec:
 selector:
 matchLabels:
 app: lxcfs
 template:
 metadata:
 labels:
 app: lxcfs
 spec:
 hostPID: true
 tolerations:
 - key: node-role.kubernetes.io/master
 effect: NoSchedule
 containers:
 - name: lxcfs
 image: dockerhub.nie.netease.com/whale/lxcfs:2.0.8
 imagePullPolicy: Always
 securityContext:
 privileged: true
 volumeMounts:
 - name: rootfs
 mountPath: /host
 volumes:
 - name: rootfs
 hostPath:
 path: /

注:由于 lxcfs FUSE 需要共享系統的 PID 名空間以及需要特權模式,所有我們配置了相應的容器啟動參數。

可以通過如下命令在所有集群節點上自動安裝、部署完成 lxcfs,是不是很簡單?:-)

kubectl create -f lxcfs-daemonset.yaml

那么如何在 Kubernetes 中使用 lxcfs 呢?和上文一樣,我們可以在 Pod 的定義中添加對 /proc 下面文件的 volume(文件卷)和對 volumeMounts(文件卷掛載)定義。然而這就讓 K8S 的應用部署文件變得比較復雜,有沒有辦法讓系統自動完成相應文件的掛載呢?

Kubernetes 提供了 Initializer 擴展機制,可以用于對資源創建進行攔截和注入處理,我們可以借助它優雅地完成對 lxcfs 文件的自動化掛載。

其 manifest 文件如下

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: lxcfs-initializer-default
 namespace: kube-system
rules:
- apiGroups: [*]
 resources: [deployments]
 verbs: [initialize ,  patch ,  watch ,  list]
apiVersion: v1
kind: ServiceAccount
metadata:
 name: lxcfs-initializer-service-account
 namespace: kube-system
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: lxcfs-initializer-role-binding
subjects:
- kind: ServiceAccount
 name: lxcfs-initializer-service-account
 namespace: kube-system
roleRef:
 kind: ClusterRole
 name: lxcfs-initializer-default
 apiGroup: rbac.authorization.k8s.io
apiVersion: apps/v1beta1
kind: Deployment
metadata:
 initializers:
 pending: []
 labels:
 app: lxcfs-initializer
 name: lxcfs-initializer
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: lxcfs-initializer
 name: lxcfs-initializer
 spec:
 serviceAccountName: lxcfs-initializer-service-account
 containers:
 - name: lxcfs-initializer
 image: dockerhub.nie.netease.com/whale/lxcfs-initializer:0.0.2
 imagePullPolicy: Always
 args:
 -  -annotation=initializer.kubernetes.io/lxcfs 
 -  -require-annotation=true 
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: InitializerConfiguration
metadata:
 name: lxcfs.initializer
initializers:
 - name: lxcfs.initializer.kubernetes.io
 rules:
 - apiGroups:
 -  * 
 apiVersions:
 -  * 
 resources:
 - deployments

注:這是一個典型的 Initializer 部署描述,首先我們創建了 service account lxcfs-initializer-service-account,并對其授權了 deployments 資源的查找、更改等權限。然后我們部署了一個名為 lxcfs-initializer 的 Initializer,利用上述 SA 啟動一個容器來處理對 deployments 資源的創建,如果 deployment 中包含 initializer.kubernetes.io/lxcfs 為 true 的注釋,就會對該應用中容器進行文件掛載

我們可以執行如下命令,部署完成之后就可以愉快地玩耍了

kubectl apply -f lxcfs-initializer.yaml

下面我們部署一個簡單的 Apache 應用,為其分配 256MB 內存,并且聲明了如下注釋 initializer.kubernetes.io/lxcfs : true

其 manifest 文件如下

apiVersion: apps/v1beta1
kind: Deployment
metadata:
 annotations:
  initializer.kubernetes.io/lxcfs :  true 
 labels:
 app: web
 name: web
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: web
 name: web
 spec:
 containers:
 - name: web
 image: httpd:2
 imagePullPolicy: Always
 resources:
 requests:
 memory:  256Mi 
 cpu:  500m 
 limits:
 memory:  256Mi 
 cpu:  500m

我們可以用如下方式進行部署和測試

$ kubectl create -f web.yaml 
deployment  web  created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-7f6bc6797c-rb9sk 1/1 Running 0 32s
$ kubectl exec web-7f6bc6797c-rb9sk free
 total used free shared buffers cached
Mem: 262144 2876 259268 2292 0 304
-/+ buffers/cache: 2572 259572
Swap: 0 0 0

我們可以看到 free 命令返回的 total memory 就是我們設置的容器資源容量。

我們可以檢查上述 Pod 的配置,果然相關的 procfs 文件都已經掛載正確

$ kubectl describe pod web-7f6bc6797c-rb9sk
 Mounts:
 /proc/cpuinfo from lxcfs-proc-cpuinfo (rw)
 /proc/diskstats from lxcfs-proc-diskstats (rw)
 /proc/meminfo from lxcfs-proc-meminfo (rw)
 /proc/stat from lxcfs-proc-stat (rw)
...

在 Kubernetes 中,還可以通過 Preset 實現類似的功能,篇幅有限。本文不再贅述了。

感謝各位的閱讀,以上就是“Kubernetes 容器隔離問題實例分析”的內容了,經過本文的學習后,相信大家對 Kubernetes 容器隔離問題實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關知識點的文章,歡迎關注!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-04發表,共計6337字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 佛山市| 连州市| 惠州市| 苍溪县| 中宁县| 郎溪县| 航空| 台中市| 称多县| 加查县| 溧水县| 柳江县| 鲁山县| 永修县| 洪雅县| 饶河县| 玉环县| 沙坪坝区| 翁源县| 凉城县| 思南县| 琼结县| 广州市| 阳新县| 开远市| 潮安县| 长寿区| 高密市| 共和县| 屯昌县| 轮台县| 高密市| 垫江县| 平顶山市| 界首市| 杭锦后旗| 临澧县| 平顶山市| 卢龙县| 宾阳县| 金门县|