<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Kubernetes上生產(chǎn)環(huán)境后,99%都會遇到這2個(gè)故障

          共 6279字,需瀏覽 13分鐘

           ·

          2021-10-22 10:48

          原文:https://zhuanlan.zhihu.com/p/343031257

          隨著微服務(wù)的不斷推進(jìn),使用 k8s 集群越來越多,越來越深入,隨之而來會遇到一系列的問題,本文向大家介紹實(shí)際使用 k8s 遇到的一些問題以及解決方法。

          1問題一:修復(fù) K8S 內(nèi)存泄露問題

          問題描述

          1. 當(dāng) k8s 集群運(yùn)行日久以后,有的 node 無法再新建 pod,并且出現(xiàn)如下錯(cuò)誤,當(dāng)重啟服務(wù)器之后,才可以恢復(fù)正常使用。查看 pod 狀態(tài)的時(shí)候會出現(xiàn)以下報(bào)錯(cuò)。
          applying?cgroup?…?caused:?mkdir?…no?space?left?on?device

          或者在 describe pod 的時(shí)候出現(xiàn) cannot allocate memory。

          這時(shí)候你的 k8s 集群可能就存在內(nèi)存泄露的問題了,當(dāng)創(chuàng)建的 pod 越多的時(shí)候內(nèi)存會泄露的越多,越快。

          1. 具體查看是否存在內(nèi)存泄露
          $?cat?/sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo

          當(dāng)出現(xiàn) cat: /sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo: Input/output error 則說明不存在內(nèi)存泄露的情況 如果存在內(nèi)存泄露會出現(xiàn)

          slabinfo?-?version:?2.1
          #?name?????????????????:?tunables????:?slabdata???

          解決方案

          1. 解決方法思路:關(guān)閉 runc 和 kubelet 的 kmem,因?yàn)樯墐?nèi)核的方案改動(dòng)較大,此處不采用。

          2. kmem 導(dǎo)致內(nèi)存泄露的原因:

          內(nèi)核對于每個(gè) cgroup 子系統(tǒng)的的條目數(shù)是有限制的,限制的大小定義在 kernel/cgroup.c #L139,當(dāng)正常在 cgroup 創(chuàng)建一個(gè) group 的目錄時(shí),條目數(shù)就加 1。我們遇到的情況就是因?yàn)殚_啟了 kmem accounting 功能,雖然 cgroup 的目錄刪除了,但是條目沒有回收。這樣后面就無法創(chuàng)建 65535 個(gè) cgroup 了。也就是說,在當(dāng)前內(nèi)核版本下,開啟了 kmem accounting 功能,會導(dǎo)致 memory cgroup 的條目泄漏無法回收。

          2.1 編譯 runc

          • 配置 go 語言環(huán)境
          $?wget?https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz
          $?tar?xf?go1.12.9.linux-amd64.tar.gz?-C?/usr/local/

          #?寫入bashrc
          $?vim?~/.bashrc
          $?export?GOPATH="/data/Documents"
          $?export?GOROOT="/usr/local/go"
          $?export?PATH="$GOROOT/bin:$GOPATH/bin:$PATH"
          $?export?GO111MODULE=off

          #?驗(yàn)證
          $?source?~/.bashrc
          $?go?env
          • 下載 runc 源碼
          $?mkdir?-p?/data/Documents/src/github.com/opencontainers/
          $?cd?/data/Documents/src/github.com/opencontainers/
          $?git?clone?https://github.com/opencontainers/runc
          $?cd?runc/
          $?git?checkout?v1.0.0-rc9??#?切到v1.0.0-rc9?tag
          • 編譯
          #?安裝編譯組件
          $?sudo?yum?install?libseccomp-devel
          $?make?BUILDTAGS='seccomp?nokmem'
          #?編譯完成之后會在當(dāng)前目錄下看到一個(gè)runc的可執(zhí)行文件,等kubelet編譯完成之后會將其替換

          2.2 編譯 kubelet

          • 下載 kubernetes 源碼
          $?mkdir?-p?/root/k8s/
          $?cd?/root/k8s/
          $?git?clone?https://github.com/kubernetes/kubernetes
          $?cd?kubernetes/
          $?git?checkout?v1.15.3
          • 制作編譯環(huán)境的鏡像(Dockerfile 如下)
          FROM?centos:centos7.3.1611

          ENV?GOROOT?/usr/local/go
          ENV?GOPATH?/usr/local/gopath
          ENV?PATH?/usr/local/go/bin:$PATH

          RUN?yum?install?rpm-build?which?where?rsync?gcc?gcc-c++?automake?autoconf?libtool?make?-y?\
          ????&&?curl?-L?https://studygolang.com/dl/golang/go1.12.9.linux-amd64.tar.gz?|?tar?zxvf?-?-C?/usr/local
          • 在制作好的 go 環(huán)境鏡像中來進(jìn)行編譯 kubelet
          $?docker?run??-it?--rm???-v?/root/k8s/kubernetes:/usr/local/gopath/src/k8s.io/kubernetes???build-k8s:centos-7.3-go-1.12.9-k8s-1.15.3???bash
          $?cd?/usr/local/gopath/src/k8s.io/kubernetes
          #編譯
          $?GO111MODULE=off?KUBE_GIT_TREE_STATE=clean?KUBE_GIT_VERSION=v1.15.3?make?kubelet?GOFLAGS="-tags=nokmem"
          1. 替換原有的 runc 和 kubelet
          • 將原有 runc 和 kubelet 備份
          $?mv?/usr/bin/kubelet?/home/kubelet
          $?mv?/usr/bin/docker-runc?/home/docker-runc
          • 停止 docker 和 kubelet
          $?systemctl?stop?docker
          $?systemctl?stop?kubelet
          • 將編譯好的 runc 和 kubelet 進(jìn)行替換
          $?cp?kubelet?/usr/bin/kubelet
          $?cp?kubelet?/usr/local/bin/kubelet
          $?cp?runc?/usr/bin/docker-runc
          • 檢查 kmem 是否關(guān)閉前需要將此節(jié)點(diǎn)的 pod 殺掉重啟或者重啟服務(wù)器,當(dāng)結(jié)果為 0 時(shí)成功
          $?cat?/sys/fs/cgroup/memory/kubepods/burstable/memory.kmem.usage_in_bytes
          • 檢查是否還存在內(nèi)存泄露的情況
          $?cat?/sys/fs/cgroup/memory/kubepods/memory.kmem.slabinfo

          2問題二:k8s 證書過期問題的兩種處理方法

          前情提要

          公司測試環(huán)境的 k8s 集群使用已經(jīng)很長時(shí)間了,突然有一天開發(fā)聯(lián)系我說 k8s 集群無法訪問,開始以為是測試環(huán)境的機(jī)器磁盤空間不夠了,導(dǎo)致組件異常或者把開發(fā)使用的鏡像自動(dòng)清理掉了,但是當(dāng)?shù)巧蠙C(jī)器去查驗(yàn)的時(shí)候發(fā)現(xiàn)不是這個(gè)原因。當(dāng)時(shí)覺得也很疑惑。因?yàn)殚_發(fā)環(huán)境使用人數(shù)較少,不應(yīng)該會出問題,所以就去查驗(yàn) log 的相關(guān)報(bào)錯(cuò)信息。

          問題現(xiàn)象

          出現(xiàn) k8s api 無法調(diào)取的現(xiàn)象,使用 kubectl 命令獲取資源均返回如下報(bào)錯(cuò):

          $?Unable?to?connect?to?the?server:?x509:?certificate?has?expired?or?is?not?yet?valid

          經(jīng)網(wǎng)上搜索之后發(fā)現(xiàn)應(yīng)該是 k8s 集群的證書過期了,使用命令排查證書的過期時(shí)間

          $?kubeadm?alpha?certs?check-expiration

          發(fā)現(xiàn)確實(shí)是證書過期了

          相關(guān)介紹以及問題解決

          因?yàn)槲覀兪鞘褂?kubeadm 部署的 k8s 集群,所以更新起證書也是比較方便的,默認(rèn)的證書時(shí)間有效期是一年,我們集群的 k8s 版本是 1.15.3 版本是可以使用以下命令來更新證書的,但是一年之后還是會到期,這樣就很麻煩,所以我們需要了解一下 k8s 的證書,然后我們來生成一個(gè)時(shí)間很長的證書,這樣我們就可以不用去總更新證書了。

          $?kubeadm?alpha?certs?renew?all?--config=kubeadm.yaml
          $?systemctl?restart?kubelet
          $?kubeadm?init?phase?kubeconfig?all?--config?kubeadm.yaml
          #?然后將生成的配置文件替換,重啟?kube-apiserver、kube-controller、kube-scheduler、etcd?這4個(gè)容器即可

          另外 kubeadm 會在控制面板升級的時(shí)候自動(dòng)更新所有證書,所以使用 kubeadm 搭建的集群最佳的做法是經(jīng)常升級集群,這樣可以確保你的集群保持最新狀態(tài)并保持合理的安全性。但是對于實(shí)際的生產(chǎn)環(huán)境我們可能并不會去頻繁的升級集群,所以這個(gè)時(shí)候我們就需要去手動(dòng)更新證書。

          下面我們通過調(diào)用 k8s 的 api 來實(shí)現(xiàn)更新一個(gè) 10 年的證書

          首先在 /etc/kubernetes/manifests/kube-controller-manager.yaml 文件加入配置

          spec:
          ??containers:
          ??-?command:
          ????-?kube-controller-manager
          ????#?設(shè)置證書有效期為?10年
          ????-?--experimental-cluster-signing-duration=87600h
          ????-?--client-ca-file=/etc/kubernetes/pki/ca.crt

          修改完成后 kube-controller-manager 會自動(dòng)重啟生效。然后我們需要使用下面的命令為 Kubernetes 證書 API 創(chuàng)建一個(gè)證書簽名請求。如果您設(shè)置例如 cert-manager 等外部簽名者,則會自動(dòng)批準(zhǔn)證書簽名請求(CSRs)。否者,您必須使用 kubectl certificate 命令手動(dòng)批準(zhǔn)證書。以下 kubeadm 命令輸出要批準(zhǔn)的證書名稱,然后等待批準(zhǔn)發(fā)生:

          #?需要將全部?pending?的證書全部批準(zhǔn)
          $?kubeadm?alpha?certs?renew?all?--use-api?--config?kubeadm.yaml?&

          我們還不能直接重啟控制面板的幾個(gè)組件,這是因?yàn)槭褂?kubeadm 安裝的集群對應(yīng)的 etcd 默認(rèn)是使用的 /etc/kubernetes/pki/etcd/ca.crt 這個(gè)證書進(jìn)行前面的,而上面我們用命令 kubectl certificate approve 批準(zhǔn)過后的證書是使用的默認(rèn)的 /etc/kubernetes/pki/ca.crt 證書進(jìn)行簽發(fā)的,所以我們需要替換 etcd 中的 ca 機(jī)構(gòu)證書:

          #?先拷貝靜態(tài)?Pod?資源清單
          $?cp?-r?/etc/kubernetes/manifests/?/etc/kubernetes/manifests.bak
          $?vi?/etc/kubernetes/manifests/etcd.yaml
          ......
          spec:
          ??containers:
          ??-?command:
          ????-?etcd
          ????#?修改為?CA?文件
          ????-?--peer-trusted-ca-file=/etc/kubernetes/pki/ca.crt
          ????-?--trusted-ca-file=/etc/kubernetes/pki/ca.crt
          ......
          ????volumeMounts:
          ????-?mountPath:?/var/lib/etcd
          ??????name:?etcd-data
          ????-?mountPath:?/etc/kubernetes/pki??#?更改證書目錄
          ??????name:?etcd-certs
          ??volumes:
          ??-?hostPath:
          ??????path:?/etc/kubernetes/pki??#?將?pki?目錄掛載到?etcd?中去
          ??????type:?DirectoryOrCreate
          ????name:?etcd-certs
          ??-?hostPath:
          ??????path:?/var/lib/etcd
          ??????type:?DirectoryOrCreate
          ????name:?etcd-data
          ......

          由于 kube-apiserver 要連接 etcd 集群,所以也需要重新修改對應(yīng)的 etcd ca 文件:

          $?vi?/etc/kubernetes/manifests/kube-apiserver.yaml
          ......
          spec:
          ??containers:
          ??-?command:
          ????-?kube-apiserver
          ????#?將etcd?ca文件修改為默認(rèn)的ca.crt文件
          ????-?--etcd-cafile=/etc/kubernetes/pki/ca.crt
          ......

          除此之外還需要替換 requestheader-client-ca-file 文件,默認(rèn)是 /etc/kubernetes/pki/front-proxy-ca.crt 文件,現(xiàn)在也需要替換成默認(rèn)的 CA 文件,否則使用聚合 API,比如安裝了 metrics-server 后執(zhí)行 kubectl top 命令就會報(bào)錯(cuò):

          $?cp?/etc/kubernetes/pki/ca.crt?/etc/kubernetes/pki/front-proxy-ca.crt
          $?cp?/etc/kubernetes/pki/ca.key?/etc/kubernetes/pki/front-proxy-ca.key

          這樣我們就得到了一個(gè) 10 年證書的 k8s 集群,還可以通過重新編譯 kubeadm 來實(shí)現(xiàn)一個(gè) 10 年證書的,這個(gè)我沒有嘗試,不過在初始化集群的時(shí)候也是一個(gè)方法。

          - END -

          ?推薦閱讀?

          Kubernetes 企業(yè)運(yùn)維進(jìn)階實(shí)戰(zhàn)?
          如何用 Kubernetes 實(shí)現(xiàn) CI/CD 發(fā)布流程?| 漫畫
          使用 Jenkins 構(gòu)建 CI/CD 之多分支流水線
          K8s kubectl 常用命令總結(jié)(建議收藏)
          終于明白了 DevOps 與 SRE 的區(qū)別!
          我在創(chuàng)業(yè)公司的 “云原生” 之旅
          基于Nginx實(shí)現(xiàn)灰度發(fā)布與AB測試
          編寫 Dockerfile 最佳實(shí)踐
          Kubernetes 網(wǎng)絡(luò)方案之炫酷的 Cilium
          運(yùn)維工程師不得不看的經(jīng)驗(yàn)教訓(xùn)和注意事項(xiàng)
          Kubernetes 的這些核心資源原理,你一定要了解



          點(diǎn)亮,服務(wù)器三年不宕機(jī)

          瀏覽 73
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久豆花视频 | 大香蕉a√| 操皮视频| 天天撸天天色 | 麻豆91久久久久久 |