LoginSignup
32
21

More than 3 years have passed since last update.

Kubernetesクラスター内のPodからkubectlを実行する

Last updated at Posted at 2019-01-17

Kubernetesクラスター内のPodからkubectlコマンドを実行する方法について調べたのでメモ。
Minikube v0.32.0とIBM Cloud Private v3.1.0で確認。

参考リンク

以下に丁寧な回答がある。

イメージの作成

kubectlのバイナリを配置したイメージを作る。

(参考)jqだけ含むコンテナの作成

FROM ubuntu

ubuntuをベースにイメージを作る。

Dockerfile
FROM ubuntu:18.04

RUN apt-get update \
  && apt-get install -y wget \
  && rm -rf /var/lib/apt/lists/* \
  && wget https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl \
  && mv kubectl /usr/local/bin/kubectl \
  && chmod +x /usr/local/bin/kubectl

ENTRYPOINT ["/usr/local/bin/kubectl"]
CMD [""]
docker build -t kubectl:v1.13.0 .
docker tag kubectl:v1.13.0 sotoiwa540/kubectl:v1.13.0
docker push sotoiwa540/kubectl:v1.13.0

FROM alpine

alpineをベースにする場合は以下のようにする。

Dockerfile
FROM alpine:3.8

RUN apk add --no-cache --virtual=build-deps wget \
  && wget https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl \
  && mv kubectl /usr/local/bin/kubectl \
  && chmod +x /usr/local/bin/kubectl \
  && apk del build-deps

ENTRYPOINT ["/usr/local/bin/kubectl"]
CMD [""]
docker build -t kubectl:v1.13.0-alpine .
docker tag kubectl:v1.13.0-alpine sotoiwa540/kubectl:v1.13.0-alpine
docker push sotoiwa540/kubectl:v1.13.0-alpine

utuntuとaplineでイメージサイズはこれくらい違う。ubuntuのほうはwgetとその依存パッケージを削除していないので、削除するようにしたらもう少しだけ減る。

$ docker images | grep kubectl | grep -v sotoiwa540
kubectl                               v1.13.0                84029f6e1e30        2 minutes ago       133MB
kubectl                               v1.13.0-alpine         93f11846b1be        2 hours ago         43.6MB
$

ibmcom/kubectl

ICPだとibmcom/kubectl:v1.11.1.1というイメージが既にあり、同じようにaplineにkubectlのバイナリを配置したもののようだ。

$ docker images | grep ibmcom/kubectl
mycluster.icp:8500/ibmcom/kubectl           v1.11.1.1              710a64408d49        5 months ago        65.4MB
$
$ docker run --rm -it mycluster.icp:8500/ibmcom/kubectl:v1.11.1.1 sh
/ # which kubectl
/usr/local/bin/kubectl
/ # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.6.2
PRETTY_NAME="Alpine Linux v3.6"
HOME_URL="http://alpinelinux.org"
BUG_REPORT_URL="http://bugs.alpinelinux.org"
/ #

Podの実行

Podとして実行する場合、特に何もしなくてもkubectlが使える(apiserverに接続できる)。なぜなら、kubectlがこのようにapiserverへの接続情報を設定しているため。

  • 接続するapiserverを環境変数KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORTから取得
    • KubernetesクラスターではapiserverはkubernetesというServiceリソースとして定義されていてクラスター内からService経由でアクセスできる
  • アクセストークンをコンテナにマウントされている/var/run/secrets/kubernetes.io/serviceaccount/tokenから取得
  • apiserverのサーバー証明書をコンテナにマウントされている/var/run/secrets/kubernetes.io/serviceaccount/ca.crtから取得

Podとして実行してみる。

kubectl-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: kubectl
  name: kubectl-pod
spec:
  containers:
  - name: kubectl
    image: sotoiwa540/kubectl:v1.13.0
    command:
    - tail
    - -f
    - /dev/null
kubectl apply -f kubectl-pod.yaml

トークンと証明書はPodが実行されるときにKubernetesによって必ず自動的にマウントされている。

$ kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
kubectl-pod   1/1     Running   0          4s
$ kubectl get po kubectl-pod -o yaml
apiVersion: v1
kind: Pod
metadata:
...
  name: kubectl-pod
  namespace: default
...
spec:
  containers:
...
    image: sotoiwa540/kubectl:v1.13.0
    imagePullPolicy: IfNotPresent
    name: kubectl
...
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-cn7gt
      readOnly: true
...
  serviceAccount: default
  serviceAccountName: default
...
  volumes:
  - name: default-token-cn7gt
    secret:
      defaultMode: 420
      secretName: default-token-cn7gt
...
$

ただしこれだけではapiserverに接続できるものの、NamespaceのデフォルトのServiceAccountで実行しているため権限がなくPodをListすることもできない。

$ kubectl exec -it kubectl-pod -- kubectl get po
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:default" cannot list resource "pods" in API group "" in the namespace "default"
command terminated with exit code 1
$

新たにServiceAccountを作り、このServiceAccountに強力なClusterRoleを割り当てる。

$ kubectl create sa admin
serviceaccount/admin created
$

デフォルトで存在するcluster-adminのClusterRoleが強力なので、このClusterRoleを作成したServiceAccountにバインドする。
ClusterRoleはClusterRoleBindingでバインドすることもできるし、RoleBingingでバインドすることもできるが、RoleBidingでバインドした場合は権限がNamespaceに限定される

ClusterRoleBinding

はじめにClusterRoleBindingを作成する。

admin-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin
  namespace: default
kubectl apply -f admin-clusterrolebinding.yaml

PodのマニフェストにserviceAccount: adminの指定を追加する。

kubectl-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: kubectl
  name: kubectl-pod
spec:
  serviceAccount: admin
  containers:
  - name: kubectl
    image: sotoiwa540/kubectl:v1.13.0
    command:
    - tail
    - -f
    - /dev/null

Podを再作成する。

kubectl delete po kubectl-pod
kubectl apply -f kubectl-pod.yaml

kubectlでPodがリストできることを確認。

$ kubectl exec -it kubectl-pod -- kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
kubectl-pod   1/1     Running   0          30s
$ kubectl exec -it kubectl-pod -- kubectl get po -n kube-system
NAME                                        READY   STATUS    RESTARTS   AGE
coredns-576cbf47c7-blfxm                    1/1     Running   1          4d22h
coredns-576cbf47c7-pnnfc                    1/1     Running   1          4d22h
default-http-backend-5957bfbccb-lhr2p       1/1     Running   1          4d22h
etcd-minikube                               1/1     Running   1          4d22h
kube-addon-manager-minikube                 1/1     Running   1          4d22h
kube-apiserver-minikube                     1/1     Running   0          4h35m
kube-controller-manager-minikube            1/1     Running   0          4h35m
kube-proxy-qzh9m                            1/1     Running   0          4h34m
kube-scheduler-minikube                     1/1     Running   1          4d22h
kubernetes-dashboard-5bff5f8fb8-2fbwb       1/1     Running   3          4d22h
nginx-ingress-controller-6958898f8f-7z9dg   1/1     Running   3          4h21m
storage-provisioner                         1/1     Running   3          4d22h
$

一度ClusterRoleBindingを削除する。

kubectl delete clusterrolebinding admin-clusterrolebinding

RoleBinding

今度はRoleBindingを作成してみる。

admin-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: admin-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: admin
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f admin-rolebinding.yaml

同じcluster-adminのClusterRoleをバインドしているにもかかわらず、自分以外のNamespaceへの権限がない。

$ kubectl exec -it kubectl-pod -- kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
kubectl-pod   1/1     Running   0          7m37s
$ kubectl exec -it kubectl-pod -- kubectl get po -n kube-system
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:admin" cannot list resource "pods" in API group "" in the namespace "kube-system"
command terminated with exit code 1
$
32
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
21