[Slides] Consistent Hashing: Algorithmic Tradoffs

這幾天閱讀 Damian Gryski 的 blog post “Consistent Hashing: Algorithmic Tradeoffs” 整理出來的投影片 (第一版)

應該會找時間寫寫中文 blog

Consistent hashing algorithmic tradeoffs from Evan Lin

[GTG30] Introduce vgo

放上這次再 GTG (Golang Taipei Gathering 30)聚會的投影片,主要是介紹可能會放入 go 1.11 的新功能 vgo

GTG30: Introduction vgo from Evan Lin

[Kubernetes] GPU resource names in Kubernetes between Accelerators and DevicePlugin

Two ways to enable GPU in Kubernetes:

If you want to enable GPU resource in Kubernetes and want Kubelet to allocate it. You need config it as following ways:

  • Kubernetes 1.7: Using NVidia container and enable Kuberlet config feature-gates=Accelerators=true
  • Kubernetes 1.9: Using Device Plugin with Kuberlet specific config feature-gates=DevicePlugins=true

Check node if it has GPU resource:

Using kubectl command kubectl get node YOUR_NODE_NAME -o json to export all node info as json format. You should see something like:

## If you use Kubernetes Accelerator after 1.7
  "allocatable": {
        "cpu": "32",
        "memory": "263933300Ki",
        "alpha.kubernetes.io/nvidia-gpu": "4",
        "pods": "110"
    },

Detail defined in k8s.io/api/core/v1/types.go

## If you use Kubernetes Device Plugin after 1.9
  "allocatable": {
        "cpu": "32",
        "memory": "263933300Ki",
        "nvidia.com/gpu": "4",
        "pods": "110"
    }, ## Reference:

[Kubernetes] Use activeDeadlineSeconds to automatically terminate (force stop) your jobs

中文前言:

在使用 Kubernetes 的時候,可以選擇透過 Job 的方式來跑一次性的工作.但是如果希望你的工作在特定時間內一定得結束來釋放資源, 就得透過這個方式.

最近在研究這個的時候,發現有些使用上的小技巧,紀錄一下.

Preface:

If you want to force to terminate your kubernetes jobs if it exceed specific time. (e.g.: run a job no longer than 2 mins).

In this case you can use a watcher to monitor this Kubernetes jobs and terminate it if exceed specific time. Or you can refer K8S Doc:”Job Termination and Cleanup” use activeDeadlineSeconds to force terminare your jobs.

How to use activeDeadlineSeconds:

It is very easy to setup activeDeadlineSeconds in spec.

apiVersion: batch/v1
kind: Job
metadata:
  name: myjob
spec:
  backoffLimit: 5 
  activeDeadlineSeconds: 100
  template:
    spec:
      containers:
      - name: myjob
        image: busybox
        command: ["sleep", "300"]
      restartPolicy: Never

In this example, this job will be terminated after 100 seconds (if it works well :p )

Before you use activeDeadlineSeconds

  • If you ever run a job with activeDeadlineSeconds, you will need delete job before you run the same job again.
  • The job will not stop if you run the same job name with activeDeadlineSeconds
  • You will need change job name to make activeDeadlineSeconds works again. (suggest add specific tag in postfix of job name)

Reference:

[LineBot] 公告: [Line 台北流浪動物需要你] 更名為 [Line 流浪動物需要你] 並且擴大服務為全台灣

由於之前”台北開放資料”中的流浪動物資料忽然無法連上,造成之前寫的 Line Bot: 台北流浪動物需要你” 無法正常運作. 只好去找找政府的資料,”動物認領養” 開放資料. (https://data.gov.tw/dataset/9842#r0)

修改好了,希望大家繼續愛用. 如果有過年需要人陪的,可以玩玩看,年後去領養可愛的小毛球家人.

簡單說明:

  • 打任意字會隨機出現動物
  • 打”狗” 或是 “貓” 會出現相關動物領養資料

[好文介紹]Scaling Kubernetes to 2,500 Nodes

原文 Scaling Kubernetes to 2,500 Nodes

緣起

最近比較忙碌,都只能夜深人靜才能好好的來閱讀一些文章來充實自己.(公司牛人多到像牧場,只好不斷努力 lol )

OpenAI 最近有一篇技術文章,相當的值得一讀.就是他們分享他們如何管理超過 2500 個節點. 當然我們都知道,

Kubernetes 自從 1.6 之後就號稱可以乘載 5000 個節點以上,但是從 數十台到 2500 台的路上,難道不會遇到一些問題嗎? 這篇文章分享了他們遇到的問題,試著要解決與懷疑的地方,最後找到真正的問題.這篇文章適合所有 DevOp 好好的熟讀.

遇到的問題與解決方式

第一次遇到問題: 1 ~ 500 個節點之後

  • 問題徵兆:
    • kubectl 有時候會發生 timeout. (p.s. `kubectl -v=6 可以顯示所有API 細節指令)
  • 嘗試解決方式:
    • 一開始以為是 kube-apiserver 服務器過分忙碌,試著增加 proxy 來做 replica 來幫忙 load balance
    • 但是超過 10 個備份 master 的時候,他們發現問題一定不是因為 kube-apiserver 無法承受.因為 GKE 透過一台 32-core VM 就可以乘載 500台
  • 原因:
    • 扣除掉這些原因,開始要懷疑 master 上剩下的幾個服務. (etcd, kube-proxy)
    • 於是開始試試看來調整 etcd
    • 透過使用 datadog 來調查 etcd 的吞吐量,發現有異常延遲 (latency spiking ~100 ms)
    • 透過 Fio 工具來做效能評估,發現只用到了 10% 的IOPS(Input/Output Per Second) , 由於寫入延遲 (write latency 2ms),造成整個效能被拖累.
    • 試著把 SSD 從網路硬碟變成每台機器有個 local temp drive (依舊是 SSD)
    • 結果從 ~100ms —> 200us

第二次遇到問題: ~1000 個節點的時候

  • 問題徵兆:
    • 發現 kube-apiserver 每秒需要從 etcd 上面讀取 500Mb
  • 嘗試解決方式:
    • 透過 Prometheus (一種廣泛用於 Kubernetes 上面作為 Container 資料搜集與監控工具) 來查看每個 container 之間的網路流量
  • 原因:
    • 發現 Fluentd (一個作為資料與 log 轉發的工具) 與 Datadog ,太頻繁來抓取每個節點上面的資料.
    • 調低這兩個服務的抓取頻率,網路效率馬上就從 500 Mb/s 到幾乎沒有…
    • etcd 小技巧: 透過 --etcd-servers-overrides 可以將 Kubernetes Event 的資料寫入作為切割,分不同機器處理.範例為 :
    --etcd-servers-overrides=/events#https://0.example.com:2381;https://1.example.com:2381;https://2.example.com:2381
    

第三次問題: 當經營到 1000~2000節點

  • 問題徵兆:
    • 無法再寫入資料,回報 cascading failure
    • kubernetes-ec2-autoscaler 在全部的 etcd 都爆掉之後才回傳問題,並且關閉所有的 etcd
  • 嘗試解決方式:
    • 猜測 etcd 硬碟爆滿,但是檢查 SSD 硬碟空間依舊有許多空間.
    • 檢查是否有預設設定空間限制,發現有 2GB 大小限制
  • 解決方式:
    • etcd 啟動參數加上 --quota-backend-bytes
    • 修改 kubernetes-ec2-autoscaler logic 如果超過 50% 都出問題,預警性的關閉集群.

## 各種服務的優化

除了遇到的問題解決外, OpenAI 也提供他們一些設定方式. 可以幫助你更順利的在大量集群上的運作.

Kube masters 的 HA (High Availability)

一般來說,我們架設都是以一個 kube-master (主要的 Kubernetes 服務提供者,上面有 kube-apiserver, kube-schedulerkube-control-manager ) 加上多個 slave . 但是要達到 HA 設定,要根據以下的方式:

  • kube-apiserver 要設置多個服務,並且透過參數 --apiserver-count 重啟並且設定.
  • kubernetes-ec2-autoscaler 可以幫你自動關閉 idle 的資源,但是這跟 Kubernetes scheduler 的原則相反. 不過透過這些設定,可以幫助你盡量把資源集中.
{
"kind" : "Policy",
"apiVersion" : "v1",
"predicates" : [
  {"name" : "GeneralPredicates"},
  {"name" : "MatchInterPodAffinity"},
  {"name" : "NoDiskConflict"},
  {"name" : "NoVolumeZoneConflict"},
  {"name" : "PodToleratesNodeTaints"}
  ],
"priorities" : [
  {"name" : "MostRequestedPriority", "weight" : 1},
  {"name" : "InterPodAffinityPriority", "weight" : 2}
  ]
}

上面是個調整你 Kubernetes scheduler 的範例,這個範例會透過把 InterPodAffinityPriority 的權重調高,達到我們要的調整方向.更多的部分,可以參考原始範例

不過要注意,目前 Kubernetes Scheduler Policy 並不支援動態切換,需要重起你的 kube-apiserver (issue: 41600)

參考文件: VF技術部落格: 深入kubernetes调度之原理分析 – 關於 Kubernetes Scheduler 相關介紹文件(中文)

調整 scheduler policy 造成的影響

OpenAI 有使用 KubeDNS: 一個 Kubernetes 內部使用的 DNS ,但是經過不久發現

  • 問題徵兆:

    • 經常有 DNS 忽然查詢不到的 (隨機發生)
    • 超過 ~200QPS domain lookup
  • 嘗試解決問題方式:

    • 試著察看為何有這種狀態,發現有些 node 上面有跑超過 10+ KubeDNS
  • 解決方式:

    • 由於 scheduler policy 造成許多 POD 會儘量的集中.
    • KubeDNS 相當的 lightweight,所以很容易被分配到同一個節點.造成 domain lookup 集中.
    • 需要修改 POD affinity (這邊有更多相關介紹),儘量讓 KubeDNS 不要都分配到同一個節點 (node)
    affinity:
     podAntiAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - weight: 100
         labelSelector:
           matchExpressions:
           - key: k8s-app
             operator: In
             values:
             - kube-dns
         topologyKey: kubernetes.io/hostname
    

緩慢的 Docker image pulls (針對新建節點)

  • 問題徵兆:
    • 每次一個新的節點建立起來,都得花約 30mins 在 docker image pull
  • 嘗試解決方式:
    • 有一個相當龐大的 container image Dota, 裡面約莫 17GB.他影響了整個節點的 image pulling
    • 開始查看 kubelet 是否有其他選項可以讓你 image pull
  • 解決方式:
    • kubelet 加上選項 --serialize-image-pulls=false 來啟動 image pulling 來讓其他服務可以比較早 pull 參考:kubelet 啟動選項
    • 並且把 docker image 存放位置放到 SSD ,讓 image pull 更快

補充: 特地下去把 source trace 了一下

// serializeImagePulls when enabled, tells the Kubelet to pull images one
// at a time. We recommend *not* changing the default value on nodes that
// run docker daemon with version  < 1.9 or an Aufs storage backend.
// Issue #10959 has more details.
SerializeImagePulls *bool `json:"serializeImagePulls"`

增加 docker image pull 速度

此外,還可以透過以下方式來增加 pull 速度

  • kubelet 有個參數 --image-pull-progress-deadline 要提高到 30mins
  • docker daemon 有個參數 max-concurrent-download 要調到 10 才能多線程下載

網路效能的提升

Flannel 效能限制

OpenAI 節點間的網路流量,可以達到 10-15Gbit/s .但是由於 Flannel 所以導致流量會降到 ~2Gbit/s

解決方式就是將 Flannel 拿掉,使用實體網路.

  • hostNetwork: true
  • dnsPolicy: ClusterFirstWithHostNet

這裡有一些警告需要詳細閱讀

參考文章 :