Kubernetes:默認(rèn)調(diào)度器三大機(jī)制

一. 簡(jiǎn)介

在 Kubernetes 項(xiàng)目中,默認(rèn)調(diào)度器(default scheduler)的主要職責(zé)河泳,就是為一個(gè)新創(chuàng)建出來(lái)的 Pod年栓,尋找一個(gè)最合適的節(jié)點(diǎn)(Node)。
而這里“最合適”的含義纸兔,包括三層:

  • 從集群所有的節(jié)點(diǎn)中否副,根據(jù)調(diào)度算法挑選出所有可以運(yùn)行該 Pod 的節(jié)點(diǎn)。
  • 從第一步的結(jié)果中负甸,再根據(jù)調(diào)度算法挑選一個(gè)最符合條件的節(jié)點(diǎn)作為最終結(jié)果痹届。
  • 當(dāng)一個(gè)高優(yōu)先級(jí)的 Pod 調(diào)度失敗后,該 Pod 并不會(huì)被“擱置”蚕捉,而是會(huì)“擠走”某個(gè) Node 上的一些低優(yōu)先級(jí)的 Pod 柴淘。

所以在具體的調(diào)度流程中秘通,默認(rèn)調(diào)度器會(huì)首先調(diào)用一組叫作 Predicate 的調(diào)度算法敛熬,來(lái)檢查每個(gè) Node。然后话原,再調(diào)用一組叫作 Priority 的調(diào)度算法诲锹,來(lái)給上一步得到的結(jié)果里的每個(gè) Node 打分。最終的調(diào)度結(jié)果黄虱,就是得分最高的那個(gè) Node庸诱。如果出現(xiàn)資源競(jìng)爭(zhēng),那就需要通過(guò) Preemption 的搶占機(jī)制來(lái)進(jìn)行調(diào)度默勾。

二. Predicates

2.1 定義

Predicates 在調(diào)度過(guò)程中的作用聚谁,可以理解為 Filter滞诺,即:它按照調(diào)度策略,從當(dāng)前集群的所有節(jié)點(diǎn)中朵耕,“過(guò)濾”出一系列符合條件的節(jié)點(diǎn)淋叶。這些節(jié)點(diǎn),都是可以運(yùn)行待調(diào)度 Pod 的宿主機(jī)处嫌。

2.2 過(guò)濾規(guī)則

2.2.1 GeneralPredicates

GeneralPredicates 負(fù)責(zé)的是最基礎(chǔ)的調(diào)度策略斟湃。比如,PodFitsResources 計(jì)算的就是宿主機(jī)的 CPU 和內(nèi)存資源等是否夠用注暗。
PodFitsResources 檢查的只是 Pod 的 requests 字段。Kubernetes 的調(diào)度器并沒(méi)有為 GPU 等硬件資源定義具體的資源類型赚楚,而是統(tǒng)一用一種名叫 Extended Resource 的骗卜、Key-Value 格式的擴(kuò)展字段來(lái)描述的。
像上面這樣一組GeneralPredicates勇皇,正是 Kubernetes 考察一個(gè) Pod 能不能運(yùn)行在一個(gè) Node 上最基本的過(guò)濾條件焚刺。所以,GeneralPredicates 也會(huì)被其他組件(比如 kubelet)直接調(diào)用兄淫。

2.2.2 Volume 相關(guān)的過(guò)濾規(guī)則

這一組過(guò)濾規(guī)則負(fù)責(zé)的是跟容器持久化 Volume 相關(guān)的調(diào)度策略蔓姚。其中,NoDiskConflict 檢查的條件泄私,是多個(gè) Pod 聲明掛載的持久化 Volume 是否有沖突备闲。比如,AWS EBS 類型的 Volume咧纠,是不允許被兩個(gè) Pod 同時(shí)使用的泻骤。所以,當(dāng)一個(gè)名叫 A 的 EBS Volume 已經(jīng)被掛載在了某個(gè)節(jié)點(diǎn)上時(shí)演痒,另一個(gè)同樣聲明使用這個(gè) A Volume 的 Pod符欠,就不能被調(diào)度到這個(gè)節(jié)點(diǎn)上了。

2.2.3 宿主機(jī)相關(guān)的過(guò)濾規(guī)則

這一組規(guī)則主要考察待調(diào)度 Pod 是否滿足 Node 本身的某些條件诊沪。比如,PodToleratesNodeTaints晕粪,負(fù)責(zé)檢查的就是我們前面經(jīng)常用到的 Node 的“污點(diǎn)”機(jī)制渐裸。只有當(dāng) Pod 的 Toleration 字段與 Node 的 Taint 字段能夠匹配的時(shí)候,這個(gè) Pod 才能被調(diào)度到該節(jié)點(diǎn)上尚氛。

2.2.4 Pod 相關(guān)的過(guò)濾規(guī)則

這一組規(guī)則跟 GeneralPredicates 大多數(shù)是重合的洞渤。比較特殊的,是 PodAffinityPredicate讯柔。這個(gè)規(guī)則的作用护昧,是檢查待調(diào)度 Pod 與 Node 上的已有 Pod 之間的親密(affinity)和反親密(anti-affinity)關(guān)系。

2.3 小結(jié)

在具體執(zhí)行的時(shí)候捣炬, 當(dāng)開(kāi)始調(diào)度一個(gè) Pod 時(shí)怠晴,Kubernetes 調(diào)度器會(huì)同時(shí)啟動(dòng) 16 個(gè) Goroutine,來(lái)并發(fā)地為集群里的所有 Node 計(jì)算 Predicates,最后返回可以運(yùn)行這個(gè) Pod 的宿主機(jī)列表冲粤。
同時(shí)页眯,為每個(gè) Node 執(zhí)行 Predicates 時(shí),調(diào)度器會(huì)按照固定的順序來(lái)進(jìn)行檢查傀顾。這個(gè)順序碌奉,是按照 Predicates 本身的含義來(lái)確定的寒砖。

三. Priorities

3.1 定義

在 Predicates 階段完成了節(jié)點(diǎn)的“過(guò)濾”之后嫉拐,Priorities 階段的工作就是為這些節(jié)點(diǎn)打分婉徘。這里打分的范圍是 0-10 分,得分最高的節(jié)點(diǎn)就是最后被 Pod 綁定的最佳節(jié)點(diǎn)盖呼。

3.2 打分規(guī)則

3.2.1 LeastRequestedPriority

LeastRequestedPriority 是 Priorities 里最常用到的一個(gè)打分規(guī)則几晤。
公式如下:

score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2

可以看到,這個(gè)算法實(shí)際上就是在選擇空閑資源(CPU 和 Memory)最多的宿主機(jī)章钾。

3.2.2 BalancedResourceAllocation

公式如下:

score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10

其中热芹,每種資源的 Fraction 的定義是 :Pod 請(qǐng)求的資源 / 節(jié)點(diǎn)上的可用資源。而 variance 算法的作用府寒,則是計(jì)算每?jī)煞N資源 Fraction 之間的“距離”报腔。而最后選擇的,則是資源 Fraction 差距最小的節(jié)點(diǎn)纤房。

可以看出翻诉,BalancedResourceAllocation 選擇的碰煌,其實(shí)是調(diào)度完成后,所有節(jié)點(diǎn)里各種資源分配最均衡的那個(gè)節(jié)點(diǎn)芦圾,從而避免一個(gè)節(jié)點(diǎn)上 CPU 被大量分配、而 Memory 大量剩余的情況洪乍。

3.2.3 ImageLocalityPriority

ImageLocalityPriority 是在 Kubernetes v1.12 里新開(kāi)啟的調(diào)度規(guī)則,即:如果待調(diào)度 Pod 需要使用的鏡像很大役拴,并且已經(jīng)存在于某些 Node 上钾埂,那么這些 Node 的得分就會(huì)比較高褥紫。

為了避免這個(gè)算法引發(fā)調(diào)度堆疊,調(diào)度器在計(jì)算得分的時(shí)候還會(huì)根據(jù)鏡像的分布進(jìn)行優(yōu)化部念,即:如果大鏡像分布的節(jié)點(diǎn)數(shù)目很少氨菇,那么這些節(jié)點(diǎn)的權(quán)重就會(huì)被調(diào)低,從而“對(duì)沖”掉引起調(diào)度堆疊的風(fēng)險(xiǎn)乌询。

3.2.4 Others

NodeAffinityPriority 豌研、 TaintTolerationPriorityInterPodAffinityPriority 這三種 Priority。
它們與 PodMatchNodeSelector鬼佣、PodToleratesNodeTaintsPodAffinityPredicate 這三個(gè) Predicate 的含義和計(jì)算方法是類似的霜浴。但是作為 Priority,一個(gè) Node 滿足上述規(guī)則的字段數(shù)目越多房铭,它的得分就會(huì)越高温眉。

四. Preemption

4.1 場(chǎng)景

當(dāng)一個(gè)高優(yōu)先級(jí)的 Pod 調(diào)度失敗后翁狐,該 Pod 并不會(huì)被“擱置”,而是會(huì)“擠走”某個(gè) Node 上的一些低優(yōu)先級(jí)的 Pod 。這樣就可以保證這個(gè)高優(yōu)先級(jí) Pod 的調(diào)度成功砂心,這就需要用到 Preemption 搶占機(jī)制蛇耀。

4.2 原理

當(dāng)上述搶占過(guò)程發(fā)生時(shí),搶占者并不會(huì)立刻被調(diào)度到被搶占的 Node 上译暂。事實(shí)上撩炊,調(diào)度器只會(huì)將搶占者的spec.nominatedNodeName 字段拧咳,設(shè)置為被搶占的 Node 的名字,所以這就是主要方法祭衩。

4.3 案例

4.3.1 PriorityClass 設(shè)置

apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
  name: high-priority
value: 999999999
globalDefault: false
description: "This is a high-priority config."

上面這個(gè) YAML 文件阅签,定義的是一個(gè)名叫 high-priorityPriorityClass,其中 value 的值是 999999999劫乱。Kubernetes 規(guī)定锥涕,優(yōu)先級(jí)是一個(gè)32 bit的整數(shù),最大值不超過(guò)1000000000(10 億层坠,1 billion),并且值越大代表優(yōu)先級(jí)越高谦趣。而超出 10 億的值座每,其實(shí)是被 Kubernetes 保留下來(lái)分配給系統(tǒng) Pod 使用的峭梳。這樣做的目的,就是保證系統(tǒng) Pod 不會(huì)被用戶搶占掉。

4.3.2 Pod 配置

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority

這個(gè) Pod 通過(guò) priorityClassName 字段口四,聲明了要使用名叫 high-priorityPriorityClass蔓彩。當(dāng)這個(gè) Pod 被提交給 Kubernetes 之后驳概,Kubernetes 的 PriorityAdmissionController 就會(huì)自動(dòng)將這個(gè) Pod 的 spec.priority 字段設(shè)置為 999999999

4.4 隊(duì)列

Kubernetes 調(diào)度器實(shí)現(xiàn)搶占算法的一個(gè)最重要的設(shè)計(jì)探膊,就是在調(diào)度隊(duì)列的實(shí)現(xiàn)里待榔,使用了兩個(gè)不同的隊(duì)列。

4.4.1 activeQ

凡是在 activeQ 里的 Pod腌闯,都是下一個(gè)調(diào)度周期需要調(diào)度的對(duì)象雕憔。所以斤彼,當(dāng)在 Kubernetes 集群里新創(chuàng)建一個(gè) Pod 的時(shí)候,調(diào)度器會(huì)將這個(gè) Pod 入隊(duì)到 activeQ 里面嘲玫。調(diào)度器不斷從隊(duì)列里出隊(duì)(Pop)一個(gè) Pod 進(jìn)行調(diào)度并扇,實(shí)際上都是從 activeQ 里出隊(duì)的。

4.4.2 unschedulableQ

這是專門用來(lái)存放調(diào)度失敗的 Pod土陪,類似 Rabbitmq 使用的死信隊(duì)列肴熏。當(dāng)一個(gè) unschedulableQ 里的 Pod 被更新之后,調(diào)度器會(huì)自動(dòng)把這個(gè) Pod 移動(dòng)到 activeQ 里取刃。

4.4 搶占流程

4.4.1 調(diào)度器為“搶占者”尋找“被搶占者”的流程

  1. 第一步出刷,調(diào)度器會(huì)檢查這次失敗事件的原因馁龟,來(lái)確認(rèn)搶占是不是可以幫助搶占者找到一個(gè)新節(jié)點(diǎn)。這是因?yàn)橛泻芏?Predicates 的失敗是不能通過(guò)搶占來(lái)解決的却音。比如矢炼,PodFitsHost 算法(負(fù)責(zé)的是,檢查 Pod 的 nodeSelector 與 Node 的名字是否匹配)夷陋,這種情況下胰锌,除非 Node 的名字發(fā)生變化资昧,否則即使刪除再多的 Pod,搶占者也不可能調(diào)度成功格带。
  2. 第二步撤缴,如果確定搶占可以發(fā)生,那么調(diào)度器就會(huì)把自己緩存的所有節(jié)點(diǎn)信息復(fù)制一份叽唱,然后使用這個(gè)副本來(lái)模擬搶占過(guò)程屈呕。

當(dāng)遍歷完所有的節(jié)點(diǎn)之后,調(diào)度器會(huì)在上述模擬產(chǎn)生的所有搶占結(jié)果里做一個(gè)選擇尔觉,找出最佳結(jié)果凉袱。而這一步的判斷原則,就是盡量減少搶占對(duì)整個(gè)系統(tǒng)的影響侦铜。

4.4.2 調(diào)度器就真正開(kāi)始搶占

  1. 第一步专甩,調(diào)度器會(huì)檢“被搶占者”列表,清理這些 Pod 所攜帶的 nominatedNodeName 字段涤躲。
  2. 第二步,調(diào)度器會(huì)把搶占者的 nominatedNodeName贡未,設(shè)置為被搶占的 Node 的名字种樱。
  3. 第三步蒙袍,調(diào)度器會(huì)開(kāi)啟一個(gè)Goroutine,同步地刪除“被搶占者”嫩挤。

所以接下來(lái)害幅,調(diào)度器就會(huì)通過(guò)正常的調(diào)度流程把搶占者調(diào)度成功,在這個(gè)正常的調(diào)度流程里岂昭,是一切皆有可能的以现。

4.5 特殊場(chǎng)景

在為某一對(duì) Pod 和 Node 執(zhí)行 Predicates 算法的時(shí)候,如果待檢查的 Node 是一個(gè)即將被搶占的節(jié)點(diǎn)约啊,即:調(diào)度隊(duì)列里有 nominatedNodeName 字段值是該 Node 名字的 Pod 存在(“潛在的搶占者”)邑遏。那么,調(diào)度器就會(huì)對(duì)這個(gè) Node 恰矩,將同樣的 Predicates 算法運(yùn)行兩遍记盒。

4.5.1 流程

  1. 第一遍, 調(diào)度器會(huì)假設(shè)上述“潛在的搶占者”已經(jīng)運(yùn)行在這個(gè)節(jié)點(diǎn)上外傅,然后執(zhí)行 Predicates 算法纪吮。
  2. 第二遍, 調(diào)度器會(huì)正常執(zhí)行 Predicates 算法栏豺,不考慮任何“潛在的搶占者”彬碱。而只有這兩遍 Predicates 算法都能通過(guò)時(shí),這個(gè) Pod 和 Node 才會(huì)被認(rèn)為是可以綁定(bind)的奥洼。

4.5.3 原因

  1. 第一遍 Predicates 算法的原因:是由于 InterPodAntiAffinity 規(guī)則的存在巷疼。
    由于 InterPodAntiAffinity 規(guī)則關(guān)心待考察節(jié)點(diǎn)上所有 Pod 之間的互斥關(guān)系,所以我們?cè)趫?zhí)行調(diào)度算法時(shí)必須考慮灵奖,如果搶占者已經(jīng)存在于待考察 Node 上時(shí)嚼沿,待調(diào)度 Pod 還能不能調(diào)度成功。
    我們?cè)谶@一步只需要考慮那些優(yōu)先級(jí)等于或者大于待調(diào)度 Pod 的搶占者瓷患。畢竟對(duì)于其他較低優(yōu)先級(jí) Pod 來(lái)說(shuō)骡尽,待調(diào)度 Pod 總是可以通過(guò)搶占運(yùn)行在待考察 Node 上。

  2. 第二遍 Predicates 算法的原因:因?yàn)椤皾撛诘膿屨颊摺弊詈蟛灰欢〞?huì)運(yùn)行在待考察的 Node 上擅编。原因是攀细,Kubernetes 調(diào)度器并不保證搶占者一定會(huì)運(yùn)行在當(dāng)初選定的被搶占的 Node 上。

五. 總結(jié)

process
  • 調(diào)度過(guò)程如下:

待調(diào)度Pod被提交到 apiServer -> 更新到 Etcd -> 調(diào)度器 Watch Etcd 感知到有需要調(diào)度的Pod(Informer) -> 取出待調(diào)度Pod的信息 -> Predicates: 挑選出可以運(yùn)行該P(yáng)od的所有Node -> Priorities:給所有Node打分 -> 將Pod綁定到得分最高的Node上 -> 將Pod信息更新回 Etcd -> node的 kubelet 感知到 Etcd 中有自己node需要拉起的Pod -> 取出該P(yáng)od信息爱态,做基本的二次檢測(cè)(端口谭贪,資源等) -> 在node 上拉起該pod

  • 搶占過(guò)程如下:

Preemption:確定要發(fā)生搶占 -> 調(diào)度器將所有節(jié)點(diǎn)信息復(fù)制一份,開(kāi)始模擬搶占 -> 檢查副本里的每一個(gè)節(jié)點(diǎn)锦担,然后從該節(jié)點(diǎn)上逐個(gè)刪除低優(yōu)先級(jí)Pod俭识,直到滿足搶占者能運(yùn)行 -> 找到一個(gè)能運(yùn)行搶占者Pod的node -> 記錄下這個(gè)Node名字和被刪除Pod的列表 -> 模擬搶占結(jié)束 -> 開(kāi)始真正搶占 -> 刪除被搶占者的Pod,將搶占者調(diào)度到Node上

歡迎收藏個(gè)人博客: Wyatt's Blog 洞渔,非常感謝~

Reference

https://time.geekbang.org/column/article/70519?utm_campaign=guanwang&utm_source=baidu-ad&utm_medium=ppzq-pc&utm_content=title&utm_term=baidu-ad-ppzq-title
https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/
https://dominik-tornow.medium.com/the-kubernetes-scheduler-cd429abac02f
https://alibaba-cloud.medium.com/getting-started-with-kubernetes-scheduling-and-resource-management-4d819c901b8c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末套媚,一起剝皮案震驚了整個(gè)濱河市缚态,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堤瘤,老刑警劉巖玫芦,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宙橱,居然都是意外死亡姨俩,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門师郑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人调窍,你說(shuō)我怎么就攤上這事宝冕。” “怎么了邓萨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵地梨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我缔恳,道長(zhǎng)宝剖,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任歉甚,我火速辦了婚禮万细,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纸泄。我一直安慰自己赖钞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布聘裁。 她就那樣靜靜地躺著雪营,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衡便。 梳的紋絲不亂的頭發(fā)上献起,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音镣陕,去河邊找鬼谴餐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛茁彭,可吹牛的內(nèi)容都是我干的总寒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼理肺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼摄闸!你這毒婦竟也來(lái)了善镰?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤年枕,失蹤者是張志新(化名)和其女友劉穎炫欺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體熏兄,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡品洛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摩桶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桥状。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖硝清,靈堂內(nèi)的尸體忽然破棺而出辅斟,到底是詐尸還是另有隱情,我是刑警寧澤芦拿,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布士飒,位于F島的核電站,受9級(jí)特大地震影響蔗崎,放射性物質(zhì)發(fā)生泄漏酵幕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一缓苛、第九天 我趴在偏房一處隱蔽的房頂上張望芳撒。 院中可真熱鬧,春花似錦他嫡、人聲如沸番官。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)徘熔。三九已至,卻和暖如春淆党,著一層夾襖步出監(jiān)牢的瞬間酷师,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工染乌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留山孔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓荷憋,卻偏偏與公主長(zhǎng)得像台颠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355