使用者數從 0 到億,我的 K8s 踩坑血淚史

作者 | 平名 阿里服務端開發技術專家

導讀

:容器服務 Kubernetes 是目前炙手可熱的雲原生基礎設施,作者過去一年上線了一個使用者數極速增長的應用:該應用一個月內日活使用者從零至四千萬,使用者數從零到一億的裂變式增長,充分享受了容器服務快速簡便的擴容操作和高可用特性。作者使用容器服務 Kubernetes 叢集將公司內系統完全上雲 1 年多,本篇文章記錄了其中的踩坑與最佳化記錄。

關注“阿里巴巴雲原生”公眾號,回覆關鍵詞“資料”,即可獲得 2019 全年meetup 活動 PPT 合集及 K8s 最全知識圖譜。

建立叢集

建立叢集時,做好規劃,選擇最佳化好的叢集配置,可以大大減少後期運維工作,其中部分叢集的配置在建立後再也沒法修改或者修改極其麻煩。

叢集規劃

網路規劃:

網路型別: Flannel、Terway

Terway 是阿里雲容器服務自研的網路外掛,功能上完全相容 Flannel,如果保守,還是使用 Flannel

Pod 網路 CIDR

預設 16 的大網段,有效的網段或者其子網 10。0。0。0/8,172。16-31。0。0/12-16,192。168。0。0/16

Service CIDR

預設 20 的網段,可選:10。0。0。0/16-24,172。16-31。0。0/16-24,192。168。0。0/16-24

網段不能衝突重複,建立後沒法修改;

多個區域的多個交換機。

公網訪問 ApiServer

對於線上等安全要求高的叢集,可以選擇不暴露 apiserver, 只有私網 SLB, 但是這樣沒法使用雲效釋出;

日常預發等叢集,可以暴露公網 SLB 到 apiserver, 叢集建立後立即為 slb 建立訪問控制,限制 slb 只能雲效訪問;

注: K8s 每次安全漏洞幾乎都與 ApiServer 有關,對於線上 K8s 叢集,要及時升級補丁,或者不開放公網 apiserver,使用嚴格的安全組和訪問控制。

安全組

設定安全組限定訪問範圍,為 master 與 worker 機器使用。

Master 機器規劃

為了高可用,一般使用 3 節點,Master 選擇規則如下:

節點數 master 規格1-5個4C8G6-20個節點4C16G21-100個節點8C32G100-200個節點16C64G

master 機器的儲存建議高效能的 50-100G SSD,因為會執行 ETCD,作業系統佔用不超過 8G。

Worker 機器規劃

阿里雲首推神龍機器,沒有神龍機器的區域,選用高配 ECS,配置規格根據部署的 POD 規格乘以一定倍數,比如 Java 應用 pod 一般選擇 4C8G,ECS 則購買 32C64G 或者 64C128G 為好,設定部署的時候為 pod 設定固定的 request/limit;

我們選用的機器配置:

32C64G ECS

儲存。系統盤:100G SSD, 資料盤:400G 高效雲盤

作業系統:centos 7。4 64 位

叢集建立與配置

建立叢集時設定:

透過控制檯建立叢集,阿里雲容器服務提供的非常簡易的一鍵部署叢集功能,透過嚮導完成 K8S 叢集的建立;

按照以上規劃設定 master,worker 節點,掛載 /var/lib/docker 到資料盤;

設定合理的 Pod 網路 CIDR, Service CIDR ip 網段;

設定合理的安全策略,是否暴露 apiserver(需要直接雲效釋出的,需要開放公網暴露,並做嚴格的訪問控制);

ingress 選擇安全,可以使用內網,如果需要公網,可以在控制檯很方便建立,同時做好訪問控制;

kube-proxy 模式,因為 iptables 模式在更新一條規則時把 iptables 鎖住引發的效能問題,建議使用 IPVS 模式;

節點 POD 數量,預設 128 太大,一個節點不可能部署這麼多,建議改為 64;

節點服務埠訪問 (NodePort,SLB),可以適當擴大,預設的也一般足夠用。

叢集配置修改:

叢集擴容,新增已有節點(節點配置參考上文,掛載資料盤使用 /var/lib/docker)

Master 機器升配:

worker 節點變配或者移除:

kubectl drain ——ignore-daemonsets {node。name}

kubectl delete node {node。name}

ECS 升配變配

新增已有節點到叢集

名稱空間:

按照應用分組建立 namespace,對於資源佔用厲害需要限制的應用分組,設定該 NameSpace 的資源配額與限制;

授權:

子賬號如何給其他子賬號進行 RBAC 授權

透過堡壘機按應用人員設定許可權

部署設定

無狀態部署

使用無狀態部署 Deployment,參考這篇文章實現分批發布。

最佳化設定模板:

apiVersion: apps/v1beta2 kind: Deployment metadata: annotations:

http://

deployment。kubernetes。io

/revision:

‘34’ # 標籤,對映 service labels: app: {app_name}-aone name: {app_name}-aone-1 namespace: {app_name} spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: {app_name}-aone # 批次重啟更新策略 strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: app: {app_name}-aone spec: containers: # 環境變數增加時區 - env: - name: TZ value: Asia/Shanghai - image: >-

http://

registry-vpc。cn-north-2-gov-1。aliyuncs。com

/

{namespace}/{app_name}:20190820190005 imagePullPolicy: Always # 啟動前執行優雅下線摘除 服務註冊 lifecycle: preStop: exec: command: - sudo - ‘-u’ - admin - /home/{user_name}/{app_name}/bin/appctl。sh - {app_name} - stop # 存活檢查,強烈建議設定 livenessProbe: failureThreshold: 10 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 5900 timeoutSeconds: 1 name: {app_name}-aone # 就緒檢查,強烈建議設定 readinessProbe: failureThreshold: 10 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 5900 timeoutSeconds: 1 # 資源限制,這個一定要合理設定 resources: limits: cpu: ‘4’ memory: 8Gi requests: cpu: ‘4’ memory: 8Gi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File # 日誌存放目錄,對映到節點的/var/lib/docker/logs 資料盤,應用日誌目錄設定到/home/{user_name}/logs 下 volumeMounts: - mountPath: /home/{user_name}/logs name: volume-1553755418538 dnsPolicy: ClusterFirst ## 私有映象倉庫的金鑰,從保密欄位獲取 imagePullSecrets: - name: {app_name}-987 restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 # 日誌存放目錄,對映到節點的/var/lib/docker/logs 資料盤 volumes: - hostPath: path: /var/lib/docker/logs/{app_name} type: ‘’ name: volume-1553755418538

服務設定

因為容器服務的 Cloud Controller Manager 會同步刪除 service 建立關聯的 SLB,為了防止 service 配置修改誤刪除 slb 故障,並導致域名、安全等配置需要修改的坑,強烈建議 service 與 slb 解耦,service 採用 NodePort 的方式,slb 另外建立後端伺服器指向叢集節點,如果需要透傳真實 IP,並考慮負載均衡,需要遵守一定的配置規則和方法,參考這個文章。

NodePort:

apiVersion: v1 kind: Service metadata: name: {app_name} namespace: {namespaces} spec: clusterIP: 10。1。50。65 ## 策略關係到是否透傳真實 IP externalTrafficPolicy: Cluster ports: - name: {app_name}-80-7001 nodePort: 32653 port: 80 protocol: TCP targetPort: 7001 - name: {app_name}-5908-5908 nodePort: 30835 port: 5108 protocol: TCP targetPort: 5108 selector: app: {app_name} sessionAffinity: None type: NodePort status: loadBalancer: {}

然後在負載均衡管理頁面,選擇後端伺服器指向叢集的 worker 機器,設定埠為以上服務的埠:32653,完成配置,這樣在叢集 service 修改或者刪除重建的時候,slb 不會被叢集的 CCM 刪除,不會涉及到域名,安全等配置修改。同時,可以設定一些策略,需要升級修改服務配置時,分批切流等。

總結

阿里雲容器服務控制檯雖然是雲上新產品,提供了極其簡單的一鍵部署功能,以及簡便的控制檯管理。過去一年中,筆者一路見識阿里雲容器服務控制檯從簡陋向強大的轉變過程,雖然多次踩坑,但阿里雲容器服務同學認真負責和極好的服務態度讓人佩服。

容器服務管理控制檯還需要更多的考慮實際運維需求,並緊密結合已有的雲產品,比如雲效、EDAS、雲監控、日誌服務等,以應用為單位,提供更好服務。

掃描下方二維碼新增小助手,與 8000 位雲原生愛好者討論技術趨勢,實戰進階!

進群暗號:公司-崗位-城市

使用者數從 0 到億,我的 K8s 踩坑血淚史