使用serviceaccount製作kubeconfig文件

背景

有時爲了需要,我們需要給出一些具有特定集羣權限的kubeconfig文件,這時我們可以通過使用serviceAccount來製作具有一定集羣權限的kubeconfig

下面我們來使用這一技術創建一個只有greenstock命名空間權限的pod讀取權限的kubeconfig

 

代碼來源:https://gist.github.com/innovia/fbba8259042f71db98ea8d4ad19bd708

準備

1. 機器需要安裝 jq

2. serviceAccount需要配置好rbac

創建步驟

1. 創建好rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: greenstock
  name: k8s-tester-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: greenstock
  name: greenstock-pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: k8s-tester-sa-rolebinding
  namespace: k8s-tester
subjects:
  - kind: ServiceAccount
    name: k8s-tester-sa
    namespace: greenstock
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: greenstock-pod-reader

 安裝上述的文件 kubectl apply -f rbac.yaml

2.根據serviceaccount 生成kubeconfig

執行https://gist.github.com/innovia/fbba8259042f71db98ea8d4ad19bd708 這個裏面的腳本,腳本內容如下 :

#!/bin/bash
set -e
set -o pipefail

# Add user to k8s using service account, no RBAC (must create RBAC after this script)
if [[ -z "$1" ]] || [[ -z "$2" ]]; then
 echo "usage: $0 <service_account_name> <namespace>"
 exit 1
fi

SERVICE_ACCOUNT_NAME=$1
NAMESPACE="$2"
KUBECFG_FILE_NAME="/tmp/kube/k8s-${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-conf"
TARGET_FOLDER="/tmp/kube"

create_target_folder() {
    echo -n "Creating target directory to hold files in ${TARGET_FOLDER}..."
    mkdir -p "${TARGET_FOLDER}"
    printf "done"
}

create_service_account() {
    echo -e "\\nCreating a service account in ${NAMESPACE} namespace: ${SERVICE_ACCOUNT_NAME}"
    kubectl create sa "${SERVICE_ACCOUNT_NAME}" --namespace "${NAMESPACE}"
}

get_secret_name_from_service_account() {
    echo -e "\\nGetting secret of service account ${SERVICE_ACCOUNT_NAME} on ${NAMESPACE}"
    SECRET_NAME=$(kubectl get sa "${SERVICE_ACCOUNT_NAME}" --namespace="${NAMESPACE}" -o json | jq -r .secrets[].name)
    echo "Secret name: ${SECRET_NAME}"
}

extract_ca_crt_from_secret() {
    echo -e -n "\\nExtracting ca.crt from secret..."
    kubectl get secret --namespace "${NAMESPACE}" "${SECRET_NAME}" -o json | jq \
    -r '.data["ca.crt"]' | base64 -D > "${TARGET_FOLDER}/ca.crt"
    printf "done"
}

get_user_token_from_secret() {
    echo -e -n "\\nGetting user token from secret..."
    USER_TOKEN=$(kubectl get secret --namespace "${NAMESPACE}" "${SECRET_NAME}" -o json | jq -r '.data["token"]' | base64 -D)
    printf "done"
}

set_kube_config_values() {
    context=$(kubectl config current-context)
    echo -e "\\nSetting current context to: $context"

    CLUSTER_NAME=$(kubectl config get-contexts "$context" | awk '{print $3}' | tail -n 1)
    echo "Cluster name: ${CLUSTER_NAME}"

    ENDPOINT=$(kubectl config view \
    -o jsonpath="{.clusters[?(@.name == \"${CLUSTER_NAME}\")].cluster.server}")
    echo "Endpoint: ${ENDPOINT}"

    # Set up the config
    echo -e "\\nPreparing k8s-${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-conf"
    echo -n "Setting a cluster entry in kubeconfig..."
    kubectl config set-cluster "${CLUSTER_NAME}" \
    --kubeconfig="${KUBECFG_FILE_NAME}" \
    --server="${ENDPOINT}" \
    --certificate-authority="${TARGET_FOLDER}/ca.crt" \
    --embed-certs=true

    echo -n "Setting token credentials entry in kubeconfig..."
    kubectl config set-credentials \
    "${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
    --kubeconfig="${KUBECFG_FILE_NAME}" \
    --token="${USER_TOKEN}"

    echo -n "Setting a context entry in kubeconfig..."
    kubectl config set-context \
    "${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
    --kubeconfig="${KUBECFG_FILE_NAME}" \
    --cluster="${CLUSTER_NAME}" \
    --user="${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
    --namespace="${NAMESPACE}"

    echo -n "Setting the current-context in the kubeconfig file..."
    kubectl config use-context "${SERVICE_ACCOUNT_NAME}-${NAMESPACE}-${CLUSTER_NAME}" \
    --kubeconfig="${KUBECFG_FILE_NAME}"
}

create_target_folder
# create_service_account
get_secret_name_from_service_account
extract_ca_crt_from_secret
get_user_token_from_secret
set_kube_config_values

echo -e "\\nAll done! Test with:"
echo "KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods"
echo "you should not have any permissions by default - you have just created the authentication part"
echo "You will need to create RBAC permissions"
KUBECONFIG=${KUBECFG_FILE_NAME} kubectl get pods

保存腳本名稱爲makekubecf.sh,執行命令是sh makekubecf.sh k8s-tester-sa greenstock

如果執行的時候遇到makekubecf.sh: 3: set: Illegal option -o pipefail,原因和解決方案可以參考https://my.oschina.net/u/1260221/blog/817458,主要就是切換成bash

3. 執行測試

假設上面 生成的腳本kubeconfig文件爲config,執行kubectl get pod -n greensock --kubeconfig=./config

4. 開發小技巧

有時候呢,我們通過client-go在開發的時候,也可以通過這種方式來生成一個臨時,符合我們的場景的serviceaccount,使用kubeconfigpath的方式來讓我們的應用可以從集羣外訪問到我們已經開啓了rbac的集羣,具體的例子,可以查看 kubernetes-tester 項目,在項目中,我使用了一個“BuildConfigFromFlags”的方法,傳入了kubeconfig文件,然後讓應用獲取到了指定serviceaccount的身份,也就是上面 的greenstock命令空間下的k8s-tester-sa從而方便了我們調試。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章