NamespaceをプロビジョニングするOperatorがあったら、マルチテナントでクラスター運用するのが楽になるかなぁと思って作成してみています。本日はNetworkPolicyのプロビジョニング機能を作成します。
- はじめに
- Operatorを作成する
- CRDを作成する
- Controllerを追加する
- Operatorをビルドする
- Operatorをデプロイする
- Operatorを確認する
はじめに
以下の記事からNamespaceをプロビジョニングするOperatorを作成しています。以下の記事では、リクエストサイズに合わせてResourceQuotaを作成する機能を作成しました。
NamespaceをプロビジョニングするOperatorを作ってみる(サイズ編)
今回は、上記で作成したOperatorにNetworkPolicyを作成する機能を追加します。アプリケーション毎にNetworkPolicy要件は変わりますが、ログ管理やメトリクス管理などの管理系Podからの通信は許可することが多いです。従って、以下の通信要件を持ったNetworkPolicyをプロビジョニングするOperatorを作成します。
- Ingress・・・カスタムリソースのmanagedの値に応じて、通信要件を変更する。
managed: true
・・・ラベルが「app=infra」のNamespace内にあるPod(管理系Pod)からの通信を許可する。それ以外は拒否。managed: false
・・・全て許可。
- Egress・・・全て許可。
Operatorを作成する
CRDを作成する
CRで設定できる項目を定義します。pkg/apis/nspro/v1alpha1/nspro_types.goのNsproSpecにManaged bool `json:”managed”`を加えて、運用管理対象か指定できるようにします。
~~省略~~ type NsproSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file // Add custom validation using kubebuilder tags: https://book.kubebuilder.io/beyond_basics/generating_crd.html NsSize string `json:"nssize"` Managed bool `json:"managed"` } ~~省略~~
変更を加えたら、以下のコマンドで必要なコードを再生成します。
$ operator-sdk generate k8s INFO[0006] Running deepcopy code-generation for Custom Resource group versions: [nspro:[v1alpha1], ] INFO[0011] Code-generation complete.
Controllerを追加する
ControllerのReconcile関数にはnewNetworkPolicyForNSを呼び出して、リソースを作成する処理を記述します。
func (r *ReconcileNspro) Reconcile(request reconcile.Request) (reconcile.Result, error) { ~~省略~~ np := r.newNetworkPolicyForNS(instance) err = r.client.Create(context.TODO(), np) ~~省略~~ }
newNetworkPolicyforNSは以下の通りです。作成方法は他のリソースと同じですが、NetworkPolicyのAPIはvender/k8s.io/api/networking/v1/type.goに記述されています。
func (r *ReconcileNspro) newNetworkPolicyForNS(cr *nsprov1alpha1.Nspro) *networkingv1.NetworkPolicy { nsname := cr.Name namespace_labels := map[string]string{} if ( cr.Spec.Managed ) { namespace_labels["app"] = "infra" } np := &networkingv1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: nsname + "-np", Namespace: nsname, }, Spec: networkingv1.NetworkPolicySpec{ Ingress: []networkingv1.NetworkPolicyIngressRule{ { From: []networkingv1.NetworkPolicyPeer{ { NamespaceSelector: &metav1.LabelSelector{ MatchLabels: namespace_labels, }, }, }, }, }, }, } controllerutil.SetControllerReference(cr, np, r.scheme) return np }
Operatorをビルドする
作成したOperatorのコンテナイメージをビルドします。
$ operator-sdk build 192.168.64.2:32000/nspro-operator:v1
以下のコマンドでレジストリに登録します。今回はMicroK8s上のコンテナレジストリ上に登録するので、[WorkerNodeのIPアドレス]:[NodePort]/[イメージ名]:[タグ名]のように登録しておきます。
$ docker push 192.168.64.2:32000/nspro-operator:v1
Operatorをデプロイする
Operatorをデプロイします。Operatorの前にCRDを作成しないとapiVersionが利用できないので、CRDから作成します。
$ kubectl create -f deploy/crds/nspro_v1alpha1_nspro_crd.yaml customresourcedefinition.apiextensions.k8s.io/nspros.nspro.example.com created
続いてdeploy/配下にあるyamlを作成します。operator.yamlだけイメージ名を変更する必要がありました。
$ kubectl delete -f deploy/operator.yaml deployment.apps "nspro-operator" deleted $ kubectl create -f deploy/operator.yaml -n nspro-operator deployment.apps/nspro-operator created $ kubectl create -f deploy/service_account.yaml -n nspro-operator serviceaccount/nspro-operator created $ kubectl create -f deploy/role.yaml -n nspro-operator role.rbac.authorization.k8s.io/nspro-operator created $ kubectl create -f deploy/role_binding.yaml -n nspro-operator rolebinding.rbac.authorization.k8s.io/nspro-operator created
Operatorを確認する
デプロイしたOperatorが正常に動くか確認します。
largeサイズの運用管理対象とするNamespaceを作成するカスタムリソースを作成します。以下のyamlを$ kubectl create -f [ファイル名] -n [Operatorのnamespace]
で作成します。
apiVersion: nspro.example.com/v1alpha1 kind: Nspro metadata: name: np spec: nssize: large managed: true
カスタムリソース作成後、Namespaceが確認できました。
$ kubectl get ns np --show-labels NAME STATUS AGE LABELS np Active 7s managed=true,size=large
想定しているNetworkPolicyが作成されていることも確認できました。
$ kubectl describe networkpolicy np-np -n np Name: np-np Namespace: np Created on: 2020-06-28 15:26:29 +0900 JST Labels: <none> Annotations: <none> Spec: PodSelector: <none> (Allowing the specific traffic to all pods in this namespace) Allowing ingress traffic: To Port: <any> (traffic allowed to all ports) From: NamespaceSelector: app=infra Allowing egress traffic: <none> (Selected pods are isolated for egress connectivity) Policy Types: Ingress
以上です。実際の挙動確認しようと思いましたが、network-pluginが入ってないと機能しないので断念しました。