Kubernetes 究竟有沒有 LTS?
從一個(gè)有趣的問題引出很多人都在關(guān)注的 Kubernetes LTS 的問題。
有趣的問題
2019 年,一個(gè)名為 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提到了一個(gè)有趣的問題,如果一個(gè) kube-apiserver 已經(jīng)一年沒有重啟過了,那么這個(gè) kube-apiserver 就無法再正常工作了。
issue 作者給出了自己的定位的原因:kube-apiserver 沒有更新自簽的 LoopbackClient 證書相關(guān)內(nèi)容。從下面代碼中可以看到證書過期時(shí)間被設(shè)置為了 1 年。
// create self-signed cert+key with the fake server.LoopbackClientServerNameOverride and
// let the server return it when the loopback client connects.
certPem, keyPem, err := certutil.GenerateSelfSignedCertKey(server.LoopbackClientServerNameOverride, nil, nil)
if err != nil {
return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
}
certProvider, err := dynamiccertificates.NewStaticSNICertKeyContent("self-signed loopback", certPem, keyPem, server.LoopbackClientServerNameOverride)
if err != nil {
return fmt.Errorf("failed to generate self-signed certificate for loopback connection: %v", err)
}
---
// GenerateSelfSignedCertKeyWithFixtures creates a self-signed certificate and key for the given host.
// Host may be an IP or a DNS name. You may also specify additional subject alt names (either ip or dns names)
// for the certificate.
//
// If fixtureDirectory is non-empty, it is a directory path which can contain pre-generated certs. The format is:
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.crt
// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.key
// Certs/keys not existing in that directory are created.
func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, alternateDNS []string, fixtureDirectory string) ([]byte, []byte, error) {
validFrom := time.Now().Add(-time.Hour) // valid an hour earlier to avoid flakes due to clock skew
maxAge := time.Hour * 24 * 365 // one year self-signed certs注:LoopbackClient 是在 kube-apiserver 中用來訪問自身時(shí)使用的,例如 kube-apiserver 在啟動(dòng)時(shí)需要獲取 Service,EndPoint 等信息(AA 中用到了),就用到了這個(gè) LoopbackClient。
同時(shí)也給出了用來檢查自己集群相關(guān)證書過期時(shí)間的方法,可以通過重啟 kube-apiserver 來臨時(shí)解決這個(gè)問題。
# replace {Master_IP} with your master IP and 6443 with your apiserver port
curl --resolve apiserver-loopback-client:6443:{Master_IP} -k -v https://apiserver-loopback-client:6443/healthz
root@kind-control-plane:/# curl --resolve apiserver-loopback-client:6443:172.17.0.2 -k -v https://apiserver-loopback-client:6443/healthz
* Added apiserver-loopback-client:6443:172.17.0.2 to DNS cache
* Hostname apiserver-loopback-client was found in DNS cache
* Trying 172.17.0.2:6443...
* TCP_NODELAY set
* Connected to apiserver-loopback-client (172.17.0.2) port 6443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=apiserver-loopback-client@1577103676
* start date: Dec 23 11:21:16 2019 GMT
* expire date: Dec 22 11:21:16 2020 GMT
* issuer: CN=apiserver-loopback-client-ca@1577103676
* SSL certificate verify result: self signed certificate in certificate chain (19), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55d565d9c1d0)
> GET /healthz HTTP/2
> Host: apiserver-loopback-client:6443
> User-Agent: curl/7.65.3
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< cache-control: no-cache, private
< content-type: text/plain; charset=utf-8
< x-content-type-options: nosniff
< content-length: 2
< date: Wed, 23 Dec 2020 14:29:30 GMT
<
* Connection #0 to host apiserver-loopback-client left intactFeature Or Bug?
這個(gè)問題發(fā)生的概率比較低,需要讓 kube-apiserver 持續(xù)運(yùn)行 1 年才會(huì)觸發(fā),當(dāng)然你也可以通過調(diào)整服務(wù)器時(shí)間到一年后來馬上讓他復(fù)現(xiàn)。
社區(qū)大佬也是做出了回復(fù),在當(dāng)時(shí) k8s 每 3 個(gè)月發(fā)布一個(gè) minor 版本,同時(shí)遵循「N-2 支持政策」,這意味著僅 3 個(gè)最新的 minor 版本(N、N-1 和 N-2)會(huì)獲得安全和錯(cuò)誤修復(fù)。也就意味著如果集群管理員按照社區(qū)規(guī)范管理 k8s 集群的話就不會(huì)出現(xiàn)運(yùn)行了 1 年以上的 k8s 組件,也就不會(huì)觸發(fā)這個(gè)問題。
圖片
同時(shí)也提到了有一個(gè)新的提案正在討論中,用來把支持的版本從過去 9 個(gè)月提升到 12 ~ 14 個(gè)月,但在當(dāng)時(shí)這也僅僅還只是個(gè)提案。最終這個(gè) issue 并沒有被當(dāng)做是 bug,至今社區(qū)版本中此處仍然硬編碼了個(gè) 1 年的過期時(shí)間。
而神奇的是,在距離上面 issue 被提到的四年后的今天,如果你上網(wǎng)搜索一下這個(gè)問題的話,你會(huì)發(fā)現(xiàn)在阿里云官網(wǎng)文檔[2]中也提到了這個(gè)問題
API Server是ACK集群管控面的核心組件,其中內(nèi)置了用于其內(nèi)部LoopbackClient[3]服務(wù)端工作的證書。該證書在社區(qū)版本中有效期為1年[4]且無法自動(dòng)輪轉(zhuǎn),只有當(dāng)API Server Pod發(fā)生重啟時(shí),才會(huì)自動(dòng)輪轉(zhuǎn)更新。社區(qū)暫無延長該證書有效期的計(jì)劃,更多信息請(qǐng)參見#86552。
考慮到不同用戶的運(yùn)維習(xí)慣,容器服務(wù) Kubernetes 版于近期調(diào)整了該內(nèi)置證書的默認(rèn)過期時(shí)間,修改后有效期為10年。
影響范圍
API Server內(nèi)置LoopbackClient證書的有效期為1年的ACK托管集群和ACK專有集群。
- 在2023年03月15日之前創(chuàng)建的ACK集群,API Server內(nèi)置LoopbackClient證書的有效期為1年。
- 在2023年03月15日及以后新建或升級(jí)至1.20.11或以上版本的ACK集群,API Server內(nèi)置LoopbackClient證書的有效期為10年,不受影響。
阿里云文檔中說了自 2023 年 03 月 15 日之后的版本已經(jīng)設(shè)置證書有效期為 10 年,也就是說阿里云其實(shí)是修改了這部分源碼的。而且還特意在最后加了這么一句:
重要:對(duì)于短期無法操作升級(jí)的ACK專有集群,請(qǐng)登錄集群的所有Master節(jié)點(diǎn),手動(dòng)重啟API Server。
阿里云作為國內(nèi)最大的公有云廠商,最后也不得不修改代碼去解決這個(gè)問題,從側(cè)面也說明了另一個(gè)問題,即使已經(jīng) 2023 年(當(dāng)時(shí))了,還有很多公司使用的 k8s 版本是遠(yuǎn)遠(yuǎn)落后于官方支持的版本的,甚至還存在一些已經(jīng)運(yùn)行了超過一年或者快要超過一年的集群。也不知道是該替阿里云的穩(wěn)定性高興(足以支持 k8s 跑一年都不重啟),還是感慨一個(gè)四年前的問題在四年后終于得到了大家的關(guān)注。amazing and iteresting ~
Kubernetes LTS
一個(gè)如此復(fù)雜的系統(tǒng),最初的支持周期連 1 年都不到,需要用戶每年一升級(jí),升級(jí)一次工作量也大,這絕對(duì)是對(duì)用戶心智的一種折磨。從結(jié)果看,確實(shí)也是存在不少的用戶在使用過程中并沒有完全遵循社區(qū)規(guī)范。
從提案 1498-kubernetes-yearly-support-period[5] 被接受后,k8s 版本的支持時(shí)間從之前的 9 個(gè)月調(diào)整到了 14 個(gè)月,包含 12 個(gè)月的支持期和 2 個(gè)月的升級(jí)周期,v1.19 是第一個(gè)享受此待遇的版本。從提案 KEP-2572: Defining the Kubernetes Release Cadence[6] 被接受后,也就是 2020 年(有一部分新冠的原因),調(diào)整發(fā)版(minor)周期從每年四次到每年三次,v1.22 是第一個(gè)按這個(gè)節(jié)奏發(fā)版的版本。
圖片
- Support Policy during the first 12 months.
Same as the current 9 months policy.
- Support Policy during the final +2 months.
CVE assigned by Product Security Committee initiated to release branch by Product Security Committee
Cherry-pick of upgrade scenario bug fix approved by owning SIG and Patch Release Team
Only critical security patches and upgrade blocking fixes, i.e.:
但從結(jié)果看,無論是 9 還是 14,這個(gè)時(shí)間對(duì)于用戶來說仍然不夠長(要不然阿里云就沒必要在 2023 年還專門提上面問題了)。拿這個(gè)時(shí)間和眾多的 Linux 發(fā)行版 LTS 對(duì)比看的話,這個(gè)時(shí)間相當(dāng)短了。
網(wǎng)上也不斷有人為此發(fā)聲:Why Kubernetes needs an LTS?[7]。
原因如下:
第一,Kubernetes 是一個(gè)復(fù)雜的容器編排系統(tǒng),由許多不同的組件和模塊組成。這些組件和模塊需要經(jīng)過持續(xù)的維護(hù)和更新,以確保其安全性和穩(wěn)定性。通過提供 LTS 版本,可以為用戶提供一個(gè)穩(wěn)定的基礎(chǔ),使他們能夠在長期內(nèi)使用 Kubernetes 而不必頻繁升級(jí)。
其次,許多組織在使用 Kubernetes 時(shí)會(huì)構(gòu)建復(fù)雜的應(yīng)用程序和基礎(chǔ)架構(gòu)。這些應(yīng)用程序和基礎(chǔ)架構(gòu)可能依賴于特定版本的 Kubernetes,并且可能需要進(jìn)行大量的測(cè)試和驗(yàn)證才能在新版本上運(yùn)行。通過提供 LTS 版本,可以確保這些組織能夠在長期內(nèi)維持其應(yīng)用程序和基礎(chǔ)架構(gòu)的穩(wěn)定性,而不必?fù)?dān)心由于升級(jí)到新版本而導(dǎo)致的不兼容性和故障。
此外,許多組織可能面臨著合規(guī)性和監(jiān)管要求。這些要求可能要求他們使用特定版本的軟件,并且在一段時(shí)間內(nèi)保持該版本的支持。通過提供 LTS 版本,Kubernetes 可以滿足這些合規(guī)性和監(jiān)管要求,使組織能夠在其環(huán)境中使用 Kubernetes 而不必?fù)?dān)心違反規(guī)定。
最后,對(duì)于那些不具備大規(guī)模升級(jí)和遷移能力的組織來說,LTS 版本可以提供更長時(shí)間的支持和穩(wěn)定性。這些組織可能沒有足夠的資源和時(shí)間來頻繁升級(jí)和遷移他們的應(yīng)用程序和基礎(chǔ)架構(gòu)。通過提供 LTS 版本,Kubernetes 可以幫助這些組織保持其系統(tǒng)的穩(wěn)定性和可靠性,而不必承擔(dān)頻繁升級(jí)的風(fēng)險(xiǎn)和成本。
社區(qū)曾在 2019 年 2 月成立了 LTS 工作組,上面的第一個(gè)提案就是相關(guān)的產(chǎn)出,最終在 2020 年 10 月關(guān)閉了這個(gè)工作組。直到 2023 年 4 月又重新評(píng)估 LTS 的需求,7 月份正式重啟了 LTS 工作組,截止目前并沒有一些實(shí)質(zhì)性的進(jìn)展。詳情可以參考 slack[8] 或者 google 會(huì)話[9]。
拓展
雖然官方 LTS 工作組還沒有實(shí)質(zhì)進(jìn)展,但 DaoCloud 有一個(gè)項(xiàng)目專門用來維護(hù)歷史 k8s 版本,參考 klts[10],其關(guān)注點(diǎn)主要是 CVE 和 Critical issues。
- CVEs that were cherry-pick approved and merged after pull requests[10]
- CVEs that were found and fixed recently[11]
- Kubernetes-related CVEs that were found and listed on cve.org recently[12]
總結(jié)
k8s 14 個(gè)月的維護(hù)周期顯然無法滿足很多用戶的需求,社區(qū)也清楚存在這個(gè)問題,也有專門的 LTS 工作組在跟進(jìn),在不久的將來,或許能看到 kubernetes LTS 的落地。
最后還想多說一點(diǎn),在選擇使用哪個(gè)版本,升不升級(jí),什么時(shí)間升級(jí),并沒有一個(gè)絕對(duì)的對(duì)錯(cuò),適合自己的才是最好的,提防角色互換,從玩家變成被玩的人,但無論如何還是要對(duì)所負(fù)責(zé)的東西有絕對(duì)的把控力。對(duì)待一些公眾號(hào)之間對(duì)某些技術(shù)理念的爭執(zhí)(互噴)也一樣,單純意識(shí)形態(tài)上的爭論對(duì)指導(dǎo)具體工作沒有多大的意義。不可否認(rèn)里面一些觀念還是挺好的,也容易被人接受,但重要的還是要結(jié)合自己的實(shí)際場(chǎng)景,多思考,可以看看聽聽,但千萬不要著相了,即使社會(huì)主義,前面都還有中國特色。
參考資料
[1]issue#86552: https://github.com/kubernetes/kubernetes/issues/86552
[2]阿里云文檔: https://www.alibabacloud.com/help/zh/ack/product-overview/validity-period-change-for-api-server-internal-certificates
[3]code1: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/server/options/serving_with_loopback.go#L52-L61
[4]code2: https://github.com/kubernetes/kubernetes/blob/69c3b23abdbda53d14e14afc2af2bdfef23ac7b0/staging/src/k8s.io/client-go/util/cert/cert.go#L40C7-L40C19
[5]1498-kubernetes-yearly-support-period: https://github.com/kubernetes/enhancements/tree/master/keps/sig-release/1498-kubernetes-yearly-support-period
[6]2572-release-cadence: https://github.com/kubernetes/enhancements/tree/master/keps/sig-release/2572-release-cadence
[7]Why Kubernetes needs an LTS: https://matduggan.com/why-kubernetes-needs-an-lts/
[8]slack#lts: https://kubernetes.slack.com/messages/wg-lts
[9]google#lts: https://groups.google.com/a/kubernetes.io/g/wg-lts
[10]ktls: https://github.com/klts-io/kubernetes-lts
[11]cve pr: https://github.com/kubernetes/kubernetes/pulls?q=is%3Apr+is%3Amerged+label%3Acherry-pick-approved+CVE
[12]cve fixed: https://www.cvedetails.com/vulnerability-list/vendor_id-15867/product_id-34016/Kubernetes-Kubernetes.html
[13]cve k8s: https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Kubernetes






















