在kubernetes集群中配置RBAC

簡介

本文將介紹Kubernetes基于角色的訪問控制(RBAC)API對象,以及兩個(gè)常見的用例(創(chuàng)建具有受限訪問權(quán)限的用戶、POD內(nèi)通過service account訪問api)。在本文的最后,您應(yīng)該具有足夠的知識(shí)來在集群中使用RBAC策略。

從Kubernetes 1.6版本起,系統(tǒng)默認(rèn)啟用RBAC策略。 RBAC策略對于正確管理群集至關(guān)重要,因?yàn)樗鼈兪鼓梢愿鶕?jù)用戶及其在組織中的角色來指定允許的操作類型。包括:

  • 通過僅向管理員用戶授予特權(quán)操作(例如訪問機(jī)密)來保護(hù)集群。
    在集群中強(qiáng)制用戶認(rèn)證。
  • 將資源創(chuàng)建(例如pod,持久卷,部署)限制為特定的名稱空間。您還可以使用配額來確保資源使用受到限制并受到控制。
  • 讓用戶僅在其授權(quán)的名稱空間中查看資源。這使您可以隔離組織內(nèi)的資源(例如,部門之間)。
  • 由于默認(rèn)啟用了RBAC,因此在配置網(wǎng)絡(luò)(例如flanneld)或使Helm時(shí),您可能會(huì)看到類似這樣的錯(cuò)誤:
the server does not allow access to the requested resource

本文將向您展示如何使用RBAC,以便您可以正確處理此類問題。

準(zhǔn)備工作

為了充分的了解本文,建議您有一套完整的Kubernetes環(huán)境,并能按我們的步驟完成整個(gè)過程,環(huán)境要求如下:

  • Kubernetes 1.6以上版本,1.6前的版本,需要手動(dòng)啟用RBAC,如果您是在本機(jī)用minikube安裝kubernetes,命令行如下:
minikube start --extra-config=apiserver.Authorization.Mode=RBAC
  • 安裝kubectl命令行工具。
  • 安裝了OpenSSL。

RBAC API 對象

Kubernetes的一項(xiàng)基本功能是其所有資源都是模型化的API對象,該對象允許進(jìn)行CRUD(創(chuàng)建,讀取,更新,刪除)操作。 資源包括:

  • Pods.
  • PersistentVolumes.
  • ConfigMaps.
  • Deployments.
  • Nodes.
  • Secrets.
  • Namespaces.

這些資源上可能的操作示例如下:

  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec

在更高級(jí)別上,資源與API Group(API組)相關(guān)聯(lián)(例如,Pod屬于核心API group,而Deployment屬于apps API group)。 有關(guān)所有可用資源,操作和API組的更多信息,請查看官方Kubernetes API參考。

為了在Kubernetes中管理RBAC,除了資源和操作外,我們還需要理解以下概念:

  • Rules:規(guī)則是可以對屬于不同API組的一組資源執(zhí)行的一組操作。
  • Roles 和 ClusterRoles: 兩者都是規(guī)則。 Role和ClusterRole之間的區(qū)別在于范圍:在Role中,規(guī)則只適用于單個(gè)命名空間(namespace),而ClusterRole則適用于整個(gè)群集,因此Role適用于多個(gè)命名空間。 ClusterRoles還可為集群范圍內(nèi)的資源(例如節(jié)點(diǎn))定義規(guī)則。 Role和ClusterRoles都映射為集群內(nèi)的API資源。
  • Subjects:這些對應(yīng)于嘗試在集群中進(jìn)行操作的實(shí)體。共有三種類型的主題:
  • User Accounts(用戶帳戶):這些是全局帳戶,用于集群外部的用戶或程序。 Kubernetes集群中沒有關(guān)聯(lián)的資源API對象。
  • Service Accounts(服務(wù)帳戶):此帳戶是和命名空間相關(guān)的,適用于在Pod內(nèi)部運(yùn)行的進(jìn)程,這些進(jìn)程需要調(diào)用API時(shí)進(jìn)行身份驗(yàn)證。
  • Groups(組):用于引用多個(gè)帳戶,默認(rèn)情況下會(huì)創(chuàng)建一些組,例如cluster-admin(在后面的部分中進(jìn)行說明)。
  • RoleBindings 和 ClusterRoleBindings: 就像名稱的意思,這些將Subjects綁定到角色(即給定用戶可以執(zhí)行的操作)。RoleBinding將使規(guī)則在命名空間內(nèi)有效,而ClusterRoleBinding將使規(guī)則在所有命名空間內(nèi)有效。

您可以在Kubernetes官方文檔中找到每個(gè)API元素的示例。

示例1: 創(chuàng)建一個(gè)新的用戶,從遠(yuǎn)程訪問kubernetes集群

在此示例中,我們將為“開發(fā)組(development)”的"cjzhao"用戶創(chuàng)建一個(gè)獨(dú)享的命名空間(cjns),并從遠(yuǎn)程服務(wù)器訪問集群,主要包括以下對象:

  • Username: cjzhao
  • Group: development
  • Namespace: cjns

我們將添加必要的RBAC策略,以便用戶cjzhao僅在cjns命名空間內(nèi)即可完全管理deployment(即使用kubectl run命令)。 最后,我們將測試這些策略以確保它們按預(yù)期工作。

創(chuàng)建namespace

執(zhí)行kubectl create命令創(chuàng)建命名空間(以admin用戶身份):

kubectl create namespace cjns

創(chuàng)建用戶憑證(User Credentials)

Kubernetes沒有用于用戶帳戶的API。 這里我們使用OpenSSL證書(更多的認(rèn)證方式請參見Kubernetes官方文檔)來管理身份驗(yàn)證,具體步驟如下:

在kubernetes管控節(jié)點(diǎn)(或管理員機(jī)器)上執(zhí)行下面操作

  • 為您的用戶創(chuàng)建一個(gè)私鑰。在此示例中,我們將文件命名為cjzhao.key:
openssl genrsa -out cjzhao.key 2048
  • 使用您剛創(chuàng)建的私鑰(cjzhao.key)創(chuàng)建證書簽名請求cjzhao.csr。 確保在-subj部分中指定用戶名和組(CN表示用戶名,O表示用戶組)。 如前所述,我們將使用cjzhao作為名稱,使用development作為用戶組:
openssl req -new -key cjzhao.key -out cjzhao.csr -subj "/CN=cjzhao/O=development"
  • 找到您的Kubernetes群集證書頒發(fā)機(jī)構(gòu)(CA)文件。 這將負(fù)責(zé)批準(zhǔn)請求并生成訪問群集API所需的證書。 它的位置通常在/etc/kubernetes/pki /目錄下。 對于Minikube,它在?/.minikube/。 檢查目錄下是否存在ca.crt和ca.key文件,并將它們拷貝到當(dāng)前目錄。

  • 通過批準(zhǔn)您之前提出的證書簽名請求cjzhao.csr來生成最終的證書cjzhao.crt,設(shè)置證書有效期為500天,執(zhí)行如下命令:

openssl x509 -req -in cjzhao.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out cjzhao.crt -days 500
  • 將cjzhao.crt、cjzhao.key、ca.crt幾個(gè)文件打包拷貝到新的機(jī)器。

在新的機(jī)器上執(zhí)行下面操作

  • 在安裝了kubectl命令行工具的新的機(jī)器上解壓上一步中打包的文件,執(zhí)行如下命令,配置kubernetes集群、用戶憑據(jù)等信息:
//配置集群
kubectl config set-cluster MyK8sCluster --server=https://your_server_ip:6443 --certificate-authority=./ca.crt
//配置用戶信息
kubectl config set-credentials cjzhao --client-certificate=./cjzhao.crt --client-key=./cjzhao.key
//配置上文(將用戶和集群綁定)
kubectl config set-context cjzhao-context --cluster=yourcluster --namespace=cjns --user=cjzhao

配置完成后執(zhí)行如下命令:

kubectl config use-context cjzhao-context

kubectl get pods

您將看到會(huì)報(bào)下面的錯(cuò):

Error from server (Forbidden): pods is forbidden: User "cjzhao" cannot list resource "pods" in API group "" in the namespace "cjns"

創(chuàng)建用戶角色來管理Deployments

  • 使用以下內(nèi)容創(chuàng)建一個(gè)role-deployment-manager.yaml文件。 在此yaml文件中,我們創(chuàng)建規(guī)則允許用戶在Deployments,Pods和ReplicaSets對象(創(chuàng)建Deployment所必需)上執(zhí)行多個(gè)操作,這些操作屬于核心(在yaml文件中用“”表示),應(yīng)用apps和擴(kuò)展extensions API組:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: cjns
  name: deployment-manager
rules:
  - apiGroups: \["", "extensions", "apps"\]
    resources: \["deployments", "replicasets", "pods"\]
    verbs: \["get", "list", "watch", "create", "update", "patch", "delete"\] \# You can also use \["\*"\]

使用kubectl create命令在集群中創(chuàng)建Role:

kubectl create -f role-deployment-manager.yaml

將用戶cjzhao和角色綁定

使用以下內(nèi)容創(chuàng)建一個(gè)rolebinding-deployment-manager.yaml文件。 在此文件中,我們將角色綁定到cjns命名空間內(nèi)的用戶cjzhao:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: deployment-manager-binding
  namespace: cjns
subjects:
  - kind: User
    name: cjzhao
    apiGroup: ""
roleRef:
  kind: Role
  name: deployment-manager
  apiGroup: ""

通過運(yùn)行kubectl create命令部署RoleBinding:

kubectl create -f rolebinding-deployment-manager.yaml

測試RBAC規(guī)則

在新的機(jī)器上執(zhí)行下面的命令創(chuàng)建一個(gè)deployment:

kubectl create deployment --image nginx myng

執(zhí)行下面的命令查看創(chuàng)建結(jié)果:

kubectl get pods

可以看到正在運(yùn)行的pod。

為了驗(yàn)證cjzhao的權(quán)限是否是限定在cjns命名空間,我們執(zhí)行下面的命令:

kubectl get pods -n default

結(jié)果如下:

Error from server (Forbidden): pods is forbidden: User "cjzhao" cannot list resource "pods" in API group "" in the namespace "default"

說明相關(guān)的用戶權(quán)限配置成功。

示例2: 通過Service Account從集群內(nèi)的POD訪問kubernetes Api

POD內(nèi)的進(jìn)程可以通過Service Account直接訪問Kubernetes API接口,本示例我們將通過kubernetes java sdk調(diào)用api接口。

Java client SDK的相關(guān)代碼見:https://github.com/kubernetes-client/java/

本示例我們將調(diào)用API返回當(dāng)前namesapce的pod信息。

Java程序

本示例使用的是Spring boot,使用jib打包為容器鏡像。請根據(jù)您的具體情況自由發(fā)揮,只要能把您的java程序打包容器鏡像都可以。
程序代碼如下:

package cn.devincloud.demo.k8sjavaclient.controller;

import java.io.IOException;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import io.kubernetes.client.ApiClient;
import io.kubernetes.client.ApiException;
import io.kubernetes.client.Configuration;
import io.kubernetes.client.apis.CoreV1Api;
import io.kubernetes.client.models.V1Pod;
import io.kubernetes.client.models.V1PodList;
import io.kubernetes.client.util.ClientBuilder;

@RestController
public class PodController {

    @GetMapping("/pods")
    private List<String> getPods() throws IOException, ApiException{
        ApiClient client = ClientBuilder.cluster().build();
        Configuration.setDefaultApiClient(client);

        // the CoreV1Api loads default api-client from global configuration.
        CoreV1Api api = new CoreV1Api();

        // invokes the CoreV1Api client
        V1PodList list = api.listNamespacedPod("cjns", null, null, null, null, null, null, null, null, null);
        return list.getItems().stream().map(new Function<V1Pod,String>(){
            @Override
            public String apply(V1Pod t) {
                return t.getMetadata().getName();
            }
        }).collect(Collectors.toList());
    }
}

創(chuàng)建Service Account

在cjns命名空間創(chuàng)建一個(gè)Service Account: javaclient-svc-account

apiVersion: v1
kind: ServiceAccount
metadata:
  name: javaclient-svc-account
  namespace: cjns

綁定角色

我們的客戶端需要讀取cjns命名空間的pod,所有可以直接將Service Account:javaclient-svc-account與示例1中的deployment-manager角色綁定即可。

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: k8sjavaclient-rbac
  namespace: cjns
subjects:
  - kind: ServiceAccount
    name: javaclient-svc-account
    namespace: cjns
roleRef:
  kind: Role
  name: deployment-manager
  apiGroup: rbac.authorization.k8s.io

部署應(yīng)用測試

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8sjavaclient
spec:
  selector:
    matchLabels:
      app: k8sjavaclient
  template:
    metadata:
      labels:
        app: k8sjavaclient
    spec:
      serviceAccountName: javaclient-svc-account
      containers:
      - name: k8sjavaclient
        image: kube.gwunion.cn/cj/k8sjavaclient
        ports:
          - containerPort: 8080

kubernetes默認(rèn)為將Service Acccount: default 綁定到POD,本例中,我們在cjns命名空間內(nèi),default賬號(hào)沒有分配相關(guān)訪問api權(quán)限,所以在POD的定義時(shí),需要指定serviceAccountName為我們上面創(chuàng)建的javaclient-svc-account

本文到此結(jié)束,喜歡的點(diǎn)贊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容