vm.gowatana.jp

NEOにほんごVMware(仮)

vSphere with Tanzu ラボ環境構築。Part-16: Tanzu Kubernetes クラスタでの PSP 使用 / Deployment 作成編

前回は Tanzu Kubernetes クラスタに接続して、Pod を単独で起動してみました。しかし、Kubernetes で Pod を起動する場合には、Deployment や StatefulSet といったリソースを利用することが一般的だと思います。そこで今回は Deployment リソースから Pod を作成してみます。

 

前回はこちら。

 

一連の投稿のまとめはこちら。

 

今回の内容です。

 

なお、今回の一連の手順では Kubernetes の Namespace の指定を省略しており、「default」Namespace を作業対象にしています。

 

Deployment の作成(PSP エラーになるパターン)

まず、ほぼデフォルト状態の Tanzu Kubernetes クラスタに、Deployment を作成してみます。

ただし、Tanzu Kubernetes クラスタではアドミッション コントロールと呼ばれる機能が有効化されており、この時点での Pod 作成は失敗してしまいます。 

前回の投稿 でも実施したように、kubectl で Tanzu Kubernetes クラスタにログインして、Context を切り替えておきます。

$ kubectl vsphere login --insecure-skip-tls-verify --server lab-wcp-01.go-lab.jp --tanzu-kubernetes-cluster-namespace lab-ns-02 --tanzu-kubernetes-cluster-name tkg-cluster-01
$ kubectl config use-context tkg-cluster-01

 

Deployment の YAML ファイルを用意しておきます。

gist.github.com

 

そして、このファイルをもとに Deployment を作成します。

$ kubectl apply -f nginx-deploy.yml
deployment.apps/tkc-demo created

 

Deployment では、Deployment → ReplicaSet → Pod といった順でリソースが作成されますが、待っても Pod が起動されません。

$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   198.48.0.1           443/TCP    17d
service/supervisor   ClusterIP   None                 6443/TCP   17d

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tkc-demo   0/2     0            0           61s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/tkc-demo-659dff8bd   2         0         0       61s

 

これは、ReplicaSet から Pod を作成する際に、PodSecurityPolicy(pod security policy)に関係するエラーが発生しているためです。

$ kubectl describe replicasets tkc-demo-659dff8bd
Name:           tkc-demo-659dff8bd
Namespace:      default
Selector:       app=tkc-demo,pod-template-hash=659dff8bd
Labels:         app=tkc-demo
                pod-template-hash=659dff8bd
Annotations:    deployment.kubernetes.io/desired-replicas: 2
                deployment.kubernetes.io/max-replicas: 3
                deployment.kubernetes.io/revision: 1
Controlled By:  Deployment/tkc-demo
Replicas:       0 current / 2 desired
Pods Status:    0 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=tkc-demo
           pod-template-hash=659dff8bd
  Containers:
   nginx-container:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type             Status  Reason
  ----             ------  ------
  ReplicaFailure   True    FailedCreate
Events:
  Type     Reason        Age                  From                   Message
  ----     ------        ----                 ----                   -------
  Warning  FailedCreate  39s (x15 over 2m1s)  replicaset-controller  Error creating: pods "tkc-demo-659dff8bd-" is forbidden: unable to validate against any pod security policy: []

 

エラーになった Deployment は、ひとまず削除しておきます。

$ kubectl delete -f nginx-deploy.yml
deployment.apps "tkc-demo" deleted

 

それでは、PodSecurityPolicy を使用してみます。

ドキュメントは下記のあたりです。

 

PodSecurityPolicy(PSP)の確認

それでは、Deployment から Pod が起動できるように、PodSecurityPolicy(PSP)と Kubernetes のサービス アカウント(ServiceAccount)を対応させる RoleBindig を作成しておきます。

Tanzu Kubernetes クラスタには、デフォルトで vmware-system-privileged と vmware-system-restricted という PSP が作成されています。

$ kubectl get podsecuritypolicies
NAME                       PRIV    CAPS   SELINUX    RUNASUSER          FSGROUP     SUPGROUP    READONLYROOTFS   VOLUMES
vmware-system-privileged   true    *      RunAsAny   RunAsAny           RunAsAny    RunAsAny    false            *
vmware-system-restricted   false          RunAsAny   MustRunAsNonRoot   MustRunAs   MustRunAs   false            configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim

 

今回は root ユーザとして Pod を起動できる vmware-system-privileged を指定します。ちなみに、もう一つの vmware-system-restricted が指定されている状態で root で Pod 起動しようとすると、Pod のイベントとして、下記のようなエラーが発生します。

Error: container has runAsNonRoot and image will run as root 

 

RoleBinding の作成

PSP を指定した RoleBinding を作成します。下記のような YAML ファイルを用意しておきます。

  • RoleBinding の名前は rb-vmware-system-privileged を指定。
  • roleRef には、ClusterRole「psp:vmware-system-privileged」を指定。
  • subjects には system:serviceaccounts Group(すべてのサービスアカウントが含まれる)を指定。

gist.github.com

 

roleRef で指定している ClusterRole「psp:vmware-system-privileged」では、resourceNames に PSP「vmware-system-privileged」が指定されています。この ClusterRole も、デフォルトで作成されているものです。

$ kubectl get clusterrole psp:vmware-system-privileged -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: "2020-07-30T03:36:50Z"
  name: psp:vmware-system-privileged
  resourceVersion: "480"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/psp%3Avmware-system-privileged
  uid: 391f6160-44c8-4bcc-b776-184b17dce8d6
rules:
- apiGroups:
  - policy
  resourceNames:
  - vmware-system-privileged
  resources:
  - podsecuritypolicies
  verbs:
  - use

 

それでは、RoleBindig を作成します。

$ kubectl apply -f tkc-rb-privileged.yml
rolebinding.rbac.authorization.k8s.io/rb-vmware-system-privileged created

 

Deployment の作成(成功パターン)

あらためて、Deployment を作成します。

$ kubectl get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/tkc-demo-6b459d8b8d-8hfbb   1/1     Running   0          10s
pod/tkc-demo-6b459d8b8d-q7cq5   1/1     Running   0          10s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   198.48.0.1   <none>        443/TCP    17d
service/supervisor   ClusterIP   None         <none>        6443/TCP   17d

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tkc-demo   2/2     2            2           11s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/tkc-demo-6b459d8b8d   2         2         2       11s

 

これで、アドミッション コントロールなしの Kubernetes クラスタと同様にワークロード展開できるはずです。また、今回は RoleBindig を作成しましたが、デモ環境などであれば ClusterRoleBinding でクラスタ全体の設定にしてもよいと思います。

 

以上、vSphere with Tanzu ラボでの Tanzu Kubernetes クラスタ作成でした。