docker
インフラ
kubernetes
REST-API

エンタープライズ向けのサービスのインフラにkubernetesを使っています。
そのサービスの中で、あるPodからPodを作成する必要が出てきました。
AdminPodがkubernetesのMasterサーバのAPIを叩くと、同じNamespaceに”CreatedPod1”ができるといったイメージです。

k8s-api.png

ゴール

RBAC認証を設定して、ポッド内からmasterのAPIを叩いて同じNamespace内にPodを作成する。

前提

kubernetesのクラスタを物理マシンに構築済み
構築していない方はこちらを参考に
ansibleでkubernetes環境の構築 1
ansibleでkubernetes環境の構築 2

説明しないこと

kubernetesの使い方
kubernetesの基本的なサービスの説明(Podとはなんぞや。みたいな)

環境

物理マシン
Ubuntu18.04
kubernetes 1.10

必要知識

RBACとは

RBAC(Role-based access control)とは、役割ベースのアクセス制御機能のことです。

kubernetesのRBACリソースは4つのリソースがあります。
Role、ClusterRole、RoleBinding、ClusterRoleBinding。

RoleとClusterRoleは権限の設定を行って、RoleBindingとClusterRoleBindingはどのRole/ClusterRoleをどのServiceAcctountに紐付けるかを定義するためのリソースになります。

RBACについては下記の記事が非常に参考になりました。
https://qiita.com/kawasima/items/8dd7eda743f2fdcad78e

やっていく

ServiceAccountとRoleとRoleBindingを作成

createEnv.yamlというyamlファイルを作成します。
内容は、admin-saというServiceAccountをtestnsというNamespaceに作成します。
admin-roleで権限の設定を行い、admin-rolebindingでadmin-saとadmin-roleを紐づけます。

createEnv.yaml
---
#Create Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: testns
---
#Create ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-sa
  namespace: testns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: admin-role
rules:
  -
    apiGroups:
      - ""
      - apps
      - autoscaling
      - batch
      - extensions
      - policy
      - rbac.authorization.k8s.io
    resources:
      - componentstatuses
      - configmaps
      - daemonsets
      - deployments
      - events
      - endpoints
      - horizontalpodautoscalers
      - ingress
      - jobs
      - limitranges
      - namespaces
      - nodes
      - pods
      - persistentvolumes
      - persistentvolumeclaims
      - resourcequotas
      - replicasets
      - replicationcontrollers
      - serviceaccounts
      - services
    verbs: ["*"]
---
#Create RoliBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: admin-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: admin-role
subjects:
- kind: ServiceAccount
  name: admin-sa
  namespace: testns

上記のyamlファイルを実行します。

$kubectl apply -f createEnv.yaml

これでRBAC周りの設定は終わりです。

AdiminPodの作成

次に、AdminPodを作成します。
deploymentのspecのserviceAccountNameで先程作成したadmin-saを指定します。

createAdminPod.yaml
---
#Create Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: admin
  labels:
    name: admin
  namespace: testns
spec:
  replicas: 1
  selector:
    matchLabels:
      name: admin
  template:
    metadata:
      labels:
        name: admin
    spec:
      serviceAccountName: admin-sa
      containers:
      - name: admin
        image: nginx:stable-alpine
        ports:
        - name: admin-port
          containerPort: 80
      dnsConfig:
        nameservers:
          - 8.8.8.8
---
#Create Service
kind: Service
apiVersion: v1
metadata:
  name: admin
  labels:
    name: admin
  namespace: default
spec:
  selector:
    name: admin
  ports:
  - name: admin-port
    port: 80
    targetPort: 80
    protocol: TCP
  type: "NodePort"

これでAdminPodの作成が完了しました。

AdminPodからcurlでRESTAPI叩く

Deploymentを作成するために、AdminPodからcurlでRESTAPIにアクセスします。
Podにはenvironmentがあらかじめ設定されているので、こちらを使います。

# env | grep KUBERNETES
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1

下準備

最後のコマンドで、"ok"が返ってきたらOKです!

$ TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
$ CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
$ NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
$ curl -H "Authorization: Bearer $TOKEN" --cacert $CACERT $K8S/healthz
ok

curlでDeploymentを作成する

curlコマンドを実行して、Deploymentを作成します。

$ curl -X POST -H "Authorization: Bearer $TOKEN" --cacert $CACERT $K8S/apis/extensions/v1beta1/namespaces/default/deployments -H 'Content-Type:application/json' -d '{"apiVersion":"extensions/v1beta1","kind":"Deployment","metadata":{"labels":{"name":"test-api"},"name":"test-api","namespace":"gfp"},"spec":{"replicas":1,"selector":{"matchLabels":{"name":"test-api"}},"template":{"metadata":{"labels":{"name":"test-api"}},"spec":{"containers":[{"image":"nginx:stable-alpine","name":"test-api"}],"dnsConfig":{"nameservers":["8.8.8.8"]},"serviceAccountName":"default"}}}}'

curlでDeploymentを削除する

もちろん削除もできます!

$ curl -X DELETE -H "Authorization: Bearer $TOKEN" --cacert $CACERT $K8S/apis/extensions/v1beta1/namespaces/default/deployments/test-api

参考サイト

APIのDocumentはここにまとまってます!

いつもyamlで書いてるので、ツールを使ってjsonに変換しました!
http://phiary.me/yaml2json/
以上です!