K8S--集羣安全

機制說明


Kubernetes是一個分佈式集羣管理工具, 保證集羣的安全性是一個重要任務. API Server是集羣內部各個組件通訊的中介, 也是外部控制的入口. 因此Kubernetes的安全機制基本圍繞保護API Server來設計. Kubernetes使用了認證(Authentication), 鑑權(Authorization), 准入控制(Admission Control)三步來保證API Server的安全node

K8S--集羣安全

認證(Authentication)


  • HTTP Token認證 : 經過一個Token來識別合法用戶

HTTP Token的認證是用一個很長的特殊編碼方式的而且難以被模仿的字符串-token來表達客戶的一種方式. Token是一個很長的很複雜的字符串, 每一個token對應一個用戶名存儲在API Server能訪問的文件中. 當客戶點發起API 調用時, 須要在HTTP Header裏放入tokenlinux

  • HTTP Base認證: 經過用戶名 + 密碼的方式認證

用戶名+ : + 密碼用BASE64算法進行編碼後的字符串放在HTTP Request中的Heather Authorization域裏發送給服務端, 服務端收到後進行編碼, 獲取用戶名及密碼算法

  • 最嚴格的HTTPS證書認證: 基於CA根證書籤名的客戶端身份認證方式
  1. HTTPS證書認證:
    K8S--集羣安全
  • token是使用API Server私鑰簽名的JWT. 用於訪問API Server時, server端認證json

  • ca.crt, 根證書. 用於Client端驗證API Server發送的證書api

  • namespace 表示這個service-account-token的做用域名空間安全

  • Kubernetes組件對API Server的訪問: kubectl、Controller Manager、Scheduler、kubelet、kube-proxy分佈式

  • Kubernetes管理的Pod對容器的訪問: Pod(dashborad也是以Pod形式運行)ide

  • Controller Manager、Scheduler與API Server在同一臺機器, 因此直接使用API Server的非安全端口訪問, --insecure-bind-address=127.0.0.1工具

  • Kubectl、kubelet、kube-proxy訪問API Server就須要證書進行HTTPS雙向認證測試

  • 手動簽發: 經過K8S集羣的跟CA進行簽發HTTPS證書

  • 自動簽發: kubelet首次訪問API Server時, 使用token作認證, 經過後, Controller Manager會爲Kubelet生成一個證書, 之後的訪問都是用證書作認證了

2 .須要認證的節點

K8S--集羣安全

兩種類型

安全性說明:

證書頒發

3 . kubeconfig

kubeconfig文件包含集羣參數(CA證書、API Server地址), 客戶端參數(上面生成的證書和私鑰), 集羣context信息(集羣名稱, 用戶名). Kubernetes組件經過啓動時指定不一樣的kubeconfig文件能夠切換到不一樣的集羣

4 .ServiceAccount

Pod中的容器訪問API Server, 由於Pod的建立、銷燬是動態的, 因此要爲他手動生成證書就不可行了. Kubernetes使用了 Service Account解決Pod訪問API Server的認證問題

5 .Secret與SA關係

Kubernetes設計了一種資源對象 Secret. 分爲兩類 1. 用於 ServiceAccount的service-account-token, 2. 用於保存用戶自定義保密信息的Opaque. Service Account中用到包含三個部分 : Token ca.crt namespace

kubectl get secret --all-namespaces

kubectl describe secret default-token-fpmdh --all-namespaces

默認狀況下, 每一個namespace都會有一個ServiceAccount, 若是Pod在建立時沒有指定ServiceAccount, 就會使用Pod所需的namespace的ServiceAccount

K8S--集羣安全

鑑權(Authorization)


認證過程, 只是確認通訊的雙方是可信的, 能夠互相通訊. 而鑑權是肯定請求方有哪些資源的權限.API Server目前支持如下幾種受權策略(經過API Server啓動參數 --authorization-mode 設置)

  • AlwaysDeny: 表示拒絕全部的請求, 通常用於測試

  • AlwaysAllow: 容許接受全部的請求, 通常用於測試

  • ABAC(Attribute-Based Access Control) : 基於屬性的訪問控制, 表示使用用戶配置的受權規則對用戶請求進行匹配和控制 (已經被淘汰, 不能及時更新)

  • Webbook: 經過調用外部REST服務對用戶進行受權

  • RBAC(Role-Based Access Control) : 基於角色的訪問控制, 現行默認規則

RBAC受權模式

RBAC(Role-Based Access Control)基於角色的訪問控制, 在Kubernetes1.5引入, 稱爲默認標準. 相比其餘方式, 擁有如下優點:

  • 對集羣中的資源和非資源均擁有完整的覆蓋

  • 整個RBAC徹底由幾個API對象完成, 同其餘API對象同樣, 能夠用kubectl或API進行操做

  • 能夠在運行時進行調整, 無需重啓API Server

RBAC的API資源對象說明

RBAC引入了4個新的頂級資源對象: Role 、ClusterRole 、RoleBinding 、ClusterRoleBinding 4種對象類型都可以經過kubectl與API操做
K8S--集羣安全

Kubernetes並不會提供用戶管理, Kubernetes組件(kubectl、kube-proxy)或是其餘定義的用戶在向CA申請證書時, 須要提供一個證書請求文件

{
    "CN": "admin",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names":[
        {
            "c": "CN",
            "ST": "HangZhou",
            "L": "XS",
            "O": "system:masters",
            "OU": "System"
        }
    ]
}

API Server會把客戶端證書的CN字段做爲User, 把names.O字段做爲Group

kubelet使用TLS Bootstraping認證時, API Server可使用 Bootstrap Tokens或者 Token Authentication file驗證=token, 不管哪種, Kubernetes都會爲token綁定一個默認的User和Group

Pod使用ServiceAccount認證時, service-account-token中的JWT會保存User信息, 有了用戶信息,再建立一對角色/角色綁定(集羣角色/集羣角色綁定)資源對象,就能夠完成權限綁定了

Role and ClusterRole
在RBAC API中, Role表示一組規則權限. 權限只會增長(累加權限) , 不存在一個資源一開始就有不少權限而經過RBAC對其進行減小的操做; Role能夠定義在一個namespace中, 若是想要跨namespace則能夠建立ClusterRole

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: 
  namespace: default
  name: pod-reader
rules: 
- apiGroups: [""] 
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole具備與Role相同的權限角色控制能力, 不一樣的是ClusterRole是集羣級別的, ClusterRole能夠用於:

  • 集羣級別的資源控制(如: node訪問權限)

  • 非資源型endpoint是(如: /healthz 訪問)

  • 全部命名空間資源控制(如: Pods)
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: 
  name: secret-reader
rules: 
- apiGroups: [""] 
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

RoleBinding and ClusterRoleBinding

RoleBinding能夠將角色中定義的權限授予用戶或用戶組, RoleBinding包含一組權限列表(subjects) , 權限列表中包含有不一樣形式的待受權權限資源類型(User, groups, or service accounts); RoleBinding一樣包含對被Bind的Role引用; RoleBinding適用於某個命名空間內受權, 而ClusterRoleBinding適用於集羣範圍內的受權

將default命名空間的pod-readerRole授予jane用戶, 此後jane用戶在default命名空間中將具備pod-reader的權限

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: 
  name: read-pods
  namespace: default
subjects: 
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding一樣能夠引用ClusterRole來對當前namespace內用戶、用戶組或ServiceAccount進行受權, 這種操做容許集羣管理員在整個集羣內定義一些通用的ClusterRole, 而後在不一樣的namespace中使用RoleBinding來引用.

如 : 如下RoleBinding引用一個ClusterRole, 這個ClusterRole具備整個集羣內對secrets的訪問權限;可是其受權用戶dave只能訪問development空間中的secrets(由於RoleBinding定義在development命名空間)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: 
  name: read-secrets
  namespace: development
subjects: 
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

使用ClusterRoleBinding能夠對整個集羣中的全部的命名空間資源權限進行受權; 如下ClusterRoleBinding樣例展現了受權manager組內全部用戶在所有命名空間中對secrets進行訪問

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: 
  name: read-secrets-global
subjects: 
- kind: Group
  name: manager
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

Resources
Kubernetes集羣內一些資源通常以其名稱字符串來表示, 這些字符串通常會在API的URL地址中出現; 同時某些資源也會包含子資源, 例如logs資源就屬於Pods的子資源, API中URL樣例以下

GET /api/v1/namespaces/{namespace}/pods/{name}/log

若是要在RBAC受權模型中控制這些子資源的訪問權限, 能夠經過 / 分隔符來實現, 如下是 一個定義Pods資源logs訪問權限的Role定義樣例

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata: 
  namespace: default
  name: pod-and-pod-logs-reader
rules: 
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

to Subjects

RoleBinding和ClusterRoleBinding能夠將Role綁定到Subjects; Subjects能夠是Groups、users或者Service Accounts

Subjects中Users使用字符串表示, 能夠是一個普通的名字字符串, 如alice; 也能夠是email格式的郵箱地址; 甚至是一組字符串形式的數字ID. 可是Users的前綴system:是系統保留的, 集羣管理員應該確保普通用戶不會使用這個前綴格式.

Groups書寫格式與Users相同, 都爲一個字符串, 而且沒有特定的格式要求; 一樣system:前綴爲系統保留

建立一個用戶只能管理dev空間:

{
    "CN": "devuser",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names":[
        {
            "c": "CN",
            "ST": "HangZhou",
            "L": "HangZhou",
            "O": "k8s",
            "OU": "System"
        }
    ]
}

# 下載證書生成工具
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /root/devuser-csr.json | cfssljson -bare devuser

# 設置集羣參數
export KUBE_APISERVER="https://172.16.11.207:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=devuser.kubeconfig

# 設置客戶端認證參數
kubectl config set-credentials devuser \
--client-certificate=/etc/kubernetes/pki/devuser.pem
--client-key=/etc/kubernetes/pki/devuser-key.pem
--embed-certs=true \
--kubeconfig=devuser.kubeconfig

#設置上下文參數
kubectl config set-context kubernetes
--cluster=kubernetes \ 
--user=devuser \
--namespace=dev \ 
--kubeconfig=devuser.kubeconfig

# 設置上下文
kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig

cp -f ./devuser.kubeconfig /root/.kube/config

kubectl create rolebindingdevuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev

准入控制

准入控制是API Server的插件集合, 經過添加不一樣的插件, 實現額外的准入控制規則.甚至於API Server的一些主要的功能都須要經過Admission Controllers實現, 好比 : ServiceAccount

K8S1.14推薦列表

NamespaceLifecycle    LimitRanger    ServiceAccount     DefaultStorageClass    DefaultTolerationSeconds    MutatingAdmissionWebbook    ValidatingAdmissionWebbook    ResourceQuota

列舉一些插件功能:

  • namespaceLifecycle: 防止在不存在的namespace上建立對象, 方式刪除系統預置的namespace, 刪除namespace時, 連帶刪除全部的資源對象.

  • LimitRanger: 確保請求的資源不會超過資源所在的Namespace的LimitRange的限制

  • ServiceAccount: 實現了自動化添加ServiceAccount

  • ResourceQuota: 確保請求的
相關文章
相關標籤/搜索