在kubernetes集群中配置RBAC

簡介

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

從Kubernetes 1.6版本起,系統(tǒng)默認啟用RBAC策略。 RBAC策略對于正確管理群集至關(guān)重要,因為它們使您可以根據(jù)用戶及其在組織中的角色來指定允許的操作類型。包括:

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

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

準備工作

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

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

RBAC API 對象

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

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

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

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

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

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

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

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

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

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

創(chuàng)建namespace

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

kubectl create namespace cjns

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

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

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

  • 為您的用戶創(chuàng)建一個私鑰。在此示例中,我們將文件命名為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ā)機構(gòu)(CA)文件。 這將負責批準請求并生成訪問群集API所需的證書。 它的位置通常在/etc/kubernetes/pki /目錄下。 對于Minikube,它在?/.minikube/。 檢查目錄下是否存在ca.crt和ca.key文件,并將它們拷貝到當前目錄。

  • 通過批準您之前提出的證書簽名請求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幾個文件打包拷貝到新的機器。

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

  • 在安裝了kubectl命令行工具的新的機器上解壓上一步中打包的文件,執(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

您將看到會報下面的錯:

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)建一個role-deployment-manager.yaml文件。 在此yaml文件中,我們創(chuàng)建規(guī)則允許用戶在Deployments,Pods和ReplicaSets對象(創(chuàng)建Deployment所必需)上執(zhí)行多個操作,這些操作屬于核心(在yaml文件中用“”表示),應(yīng)用apps和擴展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)建一個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: ""

通過運行kubectl create命令部署RoleBinding:

kubectl create -f rolebinding-deployment-manager.yaml

測試RBAC規(guī)則

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

kubectl create deployment --image nginx myng

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

kubectl get pods

可以看到正在運行的pod。

為了驗證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)的進程可以通過Service Account直接訪問Kubernetes API接口,本示例我們將通過kubernetes java sdk調(diào)用api接口。

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

本示例我們將調(diào)用API返回當前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)建一個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默認為將Service Acccount: default 綁定到POD,本例中,我們在cjns命名空間內(nèi),default賬號沒有分配相關(guān)訪問api權(quán)限,所以在POD的定義時,需要指定serviceAccountName為我們上面創(chuàng)建的javaclient-svc-account。

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

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

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

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