Kubernetes 名稱空間入門

2020-01-05 09:45:00

名稱空間是什麼?你為什麼需要它?

kubernetes 名稱空間namespace是什麼?正如 Shakespeare 以前寫過的,我們所謂的名稱空間,或者任何其他名字,就是虛擬叢集。通過虛擬叢集,意味著 kubernetes 可以在單個叢集上提供多個 kubernetes 的叢集,類似一個在其主機抽象出來的虛擬機器。kubernetes 文件 中的解釋:

kubernetes 在一個物理叢集上提供了多個虛擬叢集。這些虛擬叢集被稱為名稱空間。

你為什麼需要名稱空間?一言以蔽之:隔離。

隔離有很多優點,如它提供了安全和乾淨的環境。如果你是基礎設施的所屬者,並且要為開發者提供環境,隔離就相當重要。你最不需要的就是,一個不熟悉你叢集是如何搭建的人去修改系統設定 —— 這可能導致所有人都無法登入。

初始名稱空間

一個叢集的三個初始名稱空間:defaultkube-systemkube-public。雖然技術上你可以用這三個名稱空間作部署,但我還是推薦你把這三個名稱空間留作系統設定用,而不是你的專案。

  • Default 用於某些沒有指明名稱空間的部署,這是一種快速建立混亂的做法,如果你在沒有正確資訊的情況下做了很多部署,將很難清理。我不會去動它,因為它只有這一個用途,而且在不止一種情況下誤導過我。
  • Kube-system 是 Kubernetes 系統相關的所有物件組成的名稱空間。任何對此名稱空間的部署都可能是危險的操作,可能對系統本身造成不可挽回的破壞。沒錯,我試過;所以我不推薦。
  • Kube-public 所有人可讀,但是這個名稱空間是為系統保留的。

用名稱空間來實現隔離

我用了多種方式通過名稱空間來實現隔離。我經常用名稱空間來把多個使用者專案分割到不同的環境。這種方式可以有效防止跨專案的汙染,因為名稱空間提供了獨立的環境。例如,使用者可以安裝不同版本的 Jenkins,如果它們的環境變數是在不同的名稱空間,就不會衝突。

這種隔離對於清理也很有幫助。如果開發小組的多個專案突然被廢棄,你可以用命令 kubectl delete ns <$NAMESPACENAME> 一鍵刪除名稱空間,清理名稱空間內的所有東西。(請確認被刪除的是正確的名稱空間。我曾經在生產環境刪除了錯誤的名稱空間,這很不好。)

如果你是基礎設施所有者,請謹慎操作,因為這可能會引發其他團隊的的故障或引發其他問題。例如,如果你建立了一個特定的名稱空間,裡面有特殊的額外安全的 DNS 功能,但是其他人刪除了它,那麼名稱空間內的所有 pod 和它們執行的應用都會被清空。所有的刪除操作在真正實施之前都應該由同事(通過 GitOps)評審一下。

雖然官方文件不建議 10 人以下團隊 使用多個名稱空間,但出於架構需要,在我自己的叢集上還是用了多個名稱空間。叢集越乾淨越好。

關於名稱空間管理員應該知道的

首先,名稱空間不能巢狀。部署只能在一個名稱空間中進行。對於版本化專案,你不一定要用名稱空間,你可以使用標籤來區分有相同名字的版本化應用。名稱空間使用配額來為不同的使用者劃分資源;例如,某個名稱空間最多能有 x 個節點。最後,所有的名稱空間對於該資源型別只能使用一個獨一無二的名字。

名稱空間命令操作

你需要安裝 MinikubeHelmkubectl 命令列,才能使用下面的名稱空間命令。我的文章《安全掃描你的 DevOps 流水線》中有它們的安裝教學,你也可以去每個專案的官方主頁去找安裝教學。我使用的是最新的 Minikube。手動安裝很快,第一次就能成功執行。

穫取你的第一組名稱空間:

jess@Athena:~$ kubectl get namespaceNAME            STATUS   AGEdefault         Active   5m23skube-public     Active   5m24skube-system     Active   5m24s

建立一個名稱空間:

jess@Athena:~$ kubectl create namespace athenanamespace/athena created

現在開發者可以部署到你建立的名稱空間了;例如,這裡是一個簡短的 Helm chart:

jess@Athena:~$ helm install teset-deploy stable/redis --namespace athenaNAME: teset-deployLAST DEPLOYED: Sat Nov 23 13:47:43 2019NAMESPACE: athenaSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:` Please be patient while the chart is being deployed `Redis can be accessed via port 6379 on the following DNS names from within your cluster:teset-deploy-redis-master.athena.svc.cluster.local for read/write operationsteset-deploy-redis-slave.athena.svc.cluster.local for read-only operations

穫取你的密碼:

export REDIS_PASSWORD=$(kubectl get secret --namespace athena teset-deploy-redis -o jsonpath="{.data.redis-password}" | base64 --decode)

連線你的 redis 服務:

  1. 執行一個你可以作為用戶端用的 Redis pod:

    kubectl run --namespace athena teset-deploy-redis-client --rm --tty -i --restart='Never' \       --env REDIS_PASSWORD=$REDIS_PASSWORD \       --image docker.io/bitnami/redis:5.0.7-debian-9-r0 -- bash 
  2. 使用 Redis CLI 連線:

    redis-cli -h teset-deploy-redis-master -a $REDIS_PASSWORDredis-cli -h teset-deploy-redis-slave -a $REDIS_PASSWORD

從叢集外連線你的資料庫:

kubectl port-forward --namespace athena svc/teset-deploy-redis-master 6379:6379 &redis-cli -h 127.0.0.1 -p 6379 -a $REDIS_PASSWORD

現在這一套部署已經完成了,你有一個在名稱空間 test-deploy 中部署的 chart。

檢視你的名稱空間中有哪些 pod:

jess@Athena:~$ kubectl get pods --namespace athenaNAME                            READY   STATUS  RESTARTS   AGEteset-deploy-redis-master-0   1/1       Running   0             2m38steset-deploy-redis-slave-0      1/1     Running   0             2m38steset-deploy-redis-slave-1      1/1     Running   0             90s

現在,你已經正式把你的應用隔離到了一個名稱空間,建立了一個只在內部通訊的虛擬叢集。

一鍵刪除所有東西:

jess@Athena:~$ kubectl delete namespace athenanamespace "athena" deleted

因為這會刪除應用的所有內部設定,所以這個刪除操作可能會持續一段時間,持續時間取決於你的部署到底有多大。

再次檢查一下所有東西是否被刪除了:

jess@Athena:~$ kubectl get pods --all-namespacesNAMESPACE       NAME                            READY   STATUS  RESTARTS   AGEkube-system   coredns-5644d7b6d9-4vxv6          1/1     Running   0             32mkube-system   coredns-5644d7b6d9-t5wn7          1/1     Running   0             32mkube-system   etcd-minikube                     1/1     Running   0             31mkube-system   kube-addon-manager-minikube       1/1     Running   0             32mkube-system   kube-apiserver-minikube           1/1     Running   0             31mkube-system   kube-controller-manager-minikube  1/1     Running   0             31mkube-system   kube-proxy-5tdmh                  1/1     Running   0             32mkube-system   kube-scheduler-minikube           1/1     Running   0             31mkube-system   storage-provisioner               1/1     Running   0             27m

這是一個所有 pod 及它們存在於的已知名稱空間的列表。你可以看到,之前建立的應用和名稱空間現在已經不在了。

名稱空間實踐

當前我是出於安全考慮才使用名稱空間,如限制使用者的許可權。你可以限制所有的東西 —— 從哪些角色可以存取名稱空間,到名稱空間可使用的叢集資源(CPU 等)的配額等級。例如,我通過資源配額和基於角色的存取控制role-based access control(RBAC)設定來確保只有允許的服務賬號可以存取名稱空間。

對於隔離方面的安全,我不希望我的私人 Jenkins 應用可以通過一個信任的本地網路被當做一個有公共 IP 地址的安全映象來存取(我不得不假定,可能會被侵襲)。

如果你很難提前計算出到底要在你的雲平台上部署多少節點(或者,就我而言,是在搞崩我的家庭伺服器之前我能部署多少個),那麼名稱空間在預算方面也很有用。雖然這超出了本文的討論範圍,而且很複雜,但值得你去調研和使用來防止你的叢集過分擴充套件。

總結

名稱空間是一個很好的隔離專案和應用的方法。本文僅是一個關於名稱空間的簡短介紹,所以我建議你更深入地研究下名稱空間,在你的實踐中更多地去使用它們。