Kubernetesクラスター内のPodからkubectl
コマンドを実行する方法について調べたのでメモ。
Minikube v0.32.0とIBM Cloud Private v3.1.0で確認。
参考リンク
以下に丁寧な回答がある。
イメージの作成
kubectl
のバイナリを配置したイメージを作る。
(参考)jqだけ含むコンテナの作成
FROM ubuntu
ubuntuをベースにイメージを作る。
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をベースにする場合は以下のようにする。
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_HOST
とKUBERNETES_SERVICE_PORT
から取得- Kubernetesクラスターではapiserverは
kubernetes
というServiceリソースとして定義されていてクラスター内からService経由でアクセスできる
- Kubernetesクラスターではapiserverは
- アクセストークンをコンテナにマウントされている
/var/run/secrets/kubernetes.io/serviceaccount/token
から取得 - apiserverのサーバー証明書をコンテナにマウントされている
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
から取得
Podとして実行してみる。
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を作成する。
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
の指定を追加する。
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を作成してみる。
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
$