Jenkins 8,793 ' Kubernetes 5,150 plugin (Kubernetes Pod Templates) runs each build agent as a Pod. It should not borrow your admin credentials: give it a ServiceAccount allowed exactly what the plugin needs in one namespace, and nothing elsewhere. The rules are the ones the plugin's repository documents (RBAC and Service Accounts covers RBAC in depth):
apiVersion: v1
kind: Namespace
metadata: { name: jenkins }
---
apiVersion: v1
kind: ServiceAccount
metadata: { name: jenkins, namespace: jenkins }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { name: jenkins-agents, namespace: jenkins }
rules:
- apiGroups: [""]
resources: [pods, pods/exec]
verbs: [create, delete, get, list, patch, update, watch]
- { apiGroups: [""], resources: [pods/log], verbs: [get, list, watch] }
- { apiGroups: [""], resources: [events], verbs: [watch] }
- { apiGroups: [""], resources: [secrets], verbs: [get] }
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: { name: jenkins-agents, namespace: jenkins }
roleRef: { apiGroup: rbac.authorization.k8s.io, kind: Role, name: jenkins-agents }
subjects: [{ kind: ServiceAccount, name: jenkins, namespace: jenkins }]
---
apiVersion: v1 # a long-lived token; deleting this Secret revokes it
kind: Secret
type: kubernetes.io/service-account-token
metadata:
name: jenkins-token
namespace: jenkins
annotations: { kubernetes.io/service-account.name: jenkins }Kubernetes fills the Secret with a signed token and the cluster's CA certificate. Build a kubeconfig from them on the in-network address (Verifying the Cluster), keep it out of Git 1,932 , and test it the way Jenkins will use it: from a throwaway container on the kind 14,561 network with only that file and the official registry.k8s.io/kubectl image:
kubectl apply -f k8s/jenkins-rbac.yaml >/dev/null
K=~/.kube/jenkins-l3-booknest.kubeconfig
get() { kubectl get secret jenkins-token -n jenkins -o jsonpath="{.data.$1}" | base64 -d; }
get 'ca\.crt' > /tmp/l3-ca.crt
kc() { kubectl --kubeconfig $K config "$@" >/dev/null; }
kc set-cluster l3-booknest --server=https://l3-booknest-control-plane:6443 \
--certificate-authority=/tmp/l3-ca.crt --embed-certs
kc set-credentials jenkins --token="$(get token)"
kc set-context jenkins --cluster=l3-booknest --user=jenkins --namespace=jenkins
kc use-context jenkins && chmod 600 $K && rm /tmp/l3-ca.crt
jk() { docker run --rm --name l3-kubectl-check --network kind -v "$K:/kubeconfig:ro" \
registry.k8s.io/kubectl:v1.37.1 --kubeconfig /kubeconfig "$@"; }
jk auth can-i create pods; jk auth can-i create pods -n default
jk auth can-i get secrets -n kube-system
jk run agent-test --image=localhost:33500/booknest-api:1.3 --restart=Never >/dev/null \
--command -- node -e 'console.log("agent Pod ran in namespace jenkins")'
jk wait --for=jsonpath='{.status.phase}'=Succeeded pod/agent-test >/dev/null
jk logs agent-test && jk delete pod agent-testyes no no agent Pod ran in namespace jenkins pod "agent-test" deleted from jenkins namespace
The account runs Pods in its namespace and nothing else. In Jenkins, store the file as a Secret file credential for the Kubernetes cloud and run docker network connect kind <jenkins-container>. Agent Pods find the controller by name, since CoreDNS 366,312 forwards unknown names to Docker 514 's DNS. Jenkins Deploy Access lets this account deploy BookNest.