天天看點

openshift踩坑日記

openshift 是紅帽做的一個 kubernetes 發行版,相當于 rancher 的競品。紅帽公司 kubernetes 的基礎上,引入了安全機制,身份驗證,網絡監控,日志可視化等特性,試圖在雲原生領域分一杯羹。

scc(Security Context Constraints)

最近在 openshift 上面部署 traefik 出現了點問題。

Error creating: pods "traefik-ingress-controller-68cc888857-" is forbidden: unable to validate against any security context constraint: [provider restricted: .spec.securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used 
spec.containers[0].securityContext.capabilities.add: Invalid value: "NET_BIND_SERVICE": capability may not be added 
spec.containers[0].securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used 
spec.containers[0].securityContext.containers[0].hostPort: Invalid value: 80: Host ports are not allowed to be used 
spec.containers[0].securityContext.containers[0].hostPort: Invalid value: 443: Host ports are not allowed to be used 
spec.containers[0].securityContext.containers[0].hostPort: Invalid value: 8080: Host ports are not allowed to be used]           

根據錯誤提示,找到了問題點在于 scc 。官方的介紹如下:

OpenShift 的 安全環境限制 (Security Context Constraints)類似於 RBAC 資源控制用戶訪問的方式,管理員可以使用安全環境限制(Security Context Constraints, SCC)來控制Pod 的權限。 您可以使用 SCC 定義 Pod 運行時必須特定條件才能被系統接受。

簡單地說,scc 是在 rbac 的基礎之上,對使用者的行為進行了一些限制。包括上文提到的hostnetwork,SecurityContext 等。相當于 openshift 在

PodSecurityPolicy

上面做了一層封裝。

預設情況下,openshift包含以下8種scc。

  1. anyuid
  2. hostaccess
  3. hostmount-anyuid
  4. hostnetwork
  5. node-exporter
  6. nonroot
  7. privileged
  8. restricted

而建立的pod資源預設歸屬于Restricted政策。管理者使用者也可以建立自己的 scc 并賦予自己的 serviceaccount:

apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
metadata:
  annotations:
    kubernetes.io/description: traefikee-scc provides all features of the restricted SCC
      but allows users to run with any UID and any GID.
  name: traefikee-scc
priority: 10

allowHostDirVolumePlugin: true
allowHostIPC: false
allowHostNetwork: false
allowHostPID: false
allowHostPorts: false
allowPrivilegeEscalation: true
allowPrivilegedContainer: false
allowedCapabilities:
- NET_BIND_SERVICE
defaultAddCapabilities: null
fsGroup:
  type: RunAsAny
groups:
- system:authenticated
readOnlyRootFilesystem: false
requiredDropCapabilities:
- MKNOD
runAsUser:
  type: RunAsAny
seLinuxContext:
  type: MustRunAs
supplementalGroups:
  type: RunAsAny
users: []
volumes:
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- projected
- secret
           
oc create -f new-sa.yaml
oc create -f new-scc.yaml
oadm policy add-scc-to-user new-scc system:serviceaccount:monitor:new-sa           

是以如果建立的資源未就緒,可以用

kubectl describe pod

看一下是否觸犯了 scc 的限制。

回到原題,我之是以想部署 traefik 是想做一個接入的控制平面。但是在 openshift 平台上面,其實有自己的一種實作,這種實作叫做 route。

route 相關問題

同域名預設情況隻允許一個命名空間

預設情況下禁止同域名跨namespace,需要啟用該特性以支援,否則建立 route 會出現 a route in another namespace holds XX 。需要修改 openshift 的内置控制器配置以支援同域名跨namespace route。

oc -n openshift-ingress-operator patch ingresscontroller/default --patch '{"spec":{"routeAdmission":{"namespaceOwnership":"InterNamespaceAllowed"}}}' --type=merge           

泛域名解析

建立泛域名解析的 route 時,會提示

wildcard routes are not allowed

openshift3可以通過設定ROUTER_ALLOW_WILDCARD_ROUTES 環境變量; openshift4不支援,該問題無解。 參考

https://github.com/openshift/enhancements/blob/master/enhancements/ingress/wildcard-admission-policy.md

ingress 轉換

為了适配大家在其他平台使用的 ingress 。openshift 做了一點相容性處理,建立 ingress 時會對應建立 route。而如果ingress 中帶 TLS ,openshift 也會轉換成對應的 route。但 openshift 的route,tls 公私鑰是直接存在 route 中的,而不是 secret 。

多path解析

如果原先的 ingress 存在針對同域名的多path字首解析。比如ingress a 監聽 域名 a 的 /a 路徑;ingress b 監聽域名 a 的 /b 路徑,那麼類似 traefik 的 url rewrite 規則,在注解裡面也需要加入 rewrite 注解。openshift 會把這個注解加入到轉換的 route

中。

annotations:
    haproxy.router.openshift.io/rewrite-target: /           

網絡政策

如果應用無法通路跨namespace service/pod,具體展現是請求長時間沒有響應。這應該是這個命名空間開啟了隔離,需要用oc用戶端賦權。

oc adm pod-network make-projects-global <project1> <project2>           

反過來,如果使用者要讓某個命名空間(在openshift裡面也叫做 project)隻能namespace 内互通路,則可以這麼操作:

oc adm pod-network isolate-projects <project1> <project2>           

CRI問題

目前已知的容器運作時有以下三個:

  1. containerd
  2. CRI-O
  3. Docker

openshift 用的是 cri-o 。如果部署的應用強依賴于 containerd/docker ,則部署會導緻失敗。比如 openkruise 項目就不支援 openshift 。

參考連結

[1]

https://ithelp.ithome.com.tw/articles/10243781

[2]

https://kubernetes.io/docs/concepts/policy/pod-security-policy/

[3]

https://cloud.tencent.com/developer/article/1603597

[4]

https://docs.openshift.com/container-platform/4.8/rest_api/network_apis/route-route-openshift-io-v1.html

[5]

https://docs.openshift.com/container-platform/3.5/admin_guide/managing_networking.html

[6]

繼續閱讀