您好,登錄后才能下訂單哦!
這篇文章主要講解了“Kubernetes容器隔離問題實例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“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 缺點:不可能要求并入內核 ## 方案二、 - Procg 方案: 把文件系統掛載進容器,替代原本的proc文件系統 - 通過讀cgroup指定的信息替代原本的/proc/meminfo信息 - https://github.com/fabiokung/procg/ 缺點:內核的cgroup中沒有公開讀取內存數據函數接口 ## 方案三、 基于lxcfs的docker容器procps軟件包升級方案 ——修改free、top、uptime等源碼 缺點:不是一個廣泛接受的方案,不說自己修改命令可能產生的bug 和成本。不同的linux版本,可能會需要不同的補丁。
為LXC準備的FUSE文件系統, 提供了如下的特性:
* a cgroupfs compatible view for unprivileged containers * a set of cgroup-aware files: * cpuinfo * meminfo * stat * uptime
用戶空間文件系統 是操作系統中的概念,指完全在用戶態實現的文件系統。
目前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庫, 非特權用戶可訪問。
站在文件系統的角度: 通過調用libfuse庫
和 內核的FUSE模塊
交互實現
兩個基本功能
讓每個容器有自身的cgroup文件系統視圖
,類似 Cgroup Namespace
提供容器內部虛擬的proc文件系統
從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
解決什么問題?
用戶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這個問題
注:以下內容來自文檔鏈接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容器隔離問題實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。