Skip to content

Instantly share code, notes, and snippets.

@felegy
Last active August 25, 2025 19:39
Show Gist options
  • Select an option

  • Save felegy/de3ac973de722f5b8bd5bd96bb2624c8 to your computer and use it in GitHub Desktop.

Select an option

Save felegy/de3ac973de722f5b8bd5bd96bb2624c8 to your computer and use it in GitHub Desktop.
Connect to Kubernetes api server inside pod, grant access a service account only own namespace

Kubernetes api server access inside pod

Create a namesepace:

$ kubectl create ns service-ns
namespace/service-ns created

Check serviceaccounts

$ kubectl -n service-ns get serviceaccounts
NAME      SECRETS   AGE
default   0         48s

Run a pod:

$ kubectl -n service-ns run test-service --image alpine -- sleep infinity
pod/test-service created

Enter the pod:

$ kubectl -n service-ns exec -it test-service -- sh
/ #

Inside pod, check apiserver access:

$ apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/community/x86_64/APKINDEX.tar.gz
(1/9) Installing brotli-libs (1.1.0-r2)
(2/9) Installing c-ares (1.34.5-r0)
(3/9) Installing libunistring (1.3-r0)
(4/9) Installing libidn2 (2.3.7-r0)
(5/9) Installing nghttp2-libs (1.65.0-r0)
(6/9) Installing libpsl (0.21.5-r3)
(7/9) Installing zstd-libs (1.5.7-r0)
(8/9) Installing libcurl (8.14.1-r1)
(9/9) Installing curl (8.14.1-r1)
Executing busybox-1.37.0-r18.trigger
OK: 12 MiB in 25 packages

$ curl -Lo /usr/bin/kubectl "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   138  100   138    0     0    974      0 --:--:-- --:--:-- --:--:--   985
100 57.3M  100 57.3M    0     0   145M      0 --:--:-- --:--:-- --:--:--  145M

$ chmod +x  /usr/bin/kubectl

$ kubectl version
Client Version: v1.33.4
Kustomize Version: v5.6.0
Server Version: v1.33.1+k3s1

$ CA_CERT=/run/secrets/kubernetes.io/serviceaccount/ca.crt
$ TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
$ NAMESPACE=$(cat /run/secrets/kubernetes.io/serviceaccount/namespace)

$ curl --cacert $CA_CERT --header "Authorization: Bearer ${TOKEN}" -X GET https://kubernetes.default.svc/api; echo
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.108.0.228:6443"
    }
  ]
}

Create kubeconfig:

$ CACERT=$(cat $CA_CERT | base64 -w0)
$ mkdir -p ~/.kube
$ chmod 700 ~/.kube
$ tee ~/.kube/config <<EOF
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ${CACERT}
    server: https://kubernetes.default.svc
  name: builder
contexts:
- context:
    cluster: builder
    namespace: ${NAMESPACE}
    user: builder
  name: builder
current-context: builder
kind: Config
users:
- name: builder
  user:
    token: ${TOKEN}
EOF

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJ...
    server: https://kubernetes.default.svc
  name: builder
contexts:
- context:
    cluster: builder
    namespace: service-ns
    user: builder
  name: builder
current-context: builder
kind: Config
users:
- name: builder
  user:
    token: eyJhbGciOiJSUzI1NiIsI...

Check kubeconfig:

$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:service-ns:default" cannot list resource "pods" in API group "" in the namespace "service-ns"

exit

OK, kubeconfig working properly but current serviceaccount does not have any access rights.

Grant access for serviceaccount (outside the pod):

$ kubectl -n service-ns apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: runner-role
  namespace: service-ns
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
EOF
role.rbac.authorization.k8s.io/runner-role created

$ kubectl -n service-ns apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: runner-role-binding
  namespace: service-ns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: runner-role
subjects:
- kind: ServiceAccount
  name: default
EOF
rolebinding.rbac.authorization.k8s.io/runner-role-binding created

Test inside the pod:

# entering in the pod
$ kubectl -n service-ns exec -it test-service -- sh 
/ #

$ kubectl get pod
NAME           READY   STATUS    RESTARTS   AGE
test-service   1/1     Running   0          82m

DONE!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment