OpenShift Service MeshのIstio CNI

Red HatでOpenShiftのサポートをしているid:nekopです。OpenShift Advent Calendar 2019の2日目のエントリです。

f:id:nekop:20191202095545p:plain

OpenShift Service MeshはIstioの製品版ですが、通常のIstioをセットアップしたときと少し構成が異なり、Istio CNIというものが利用されています。

IstioはトラフィックをインターセプトしてSidecar proxyへ流すためにiptablesのルールを利用しています。このiptablesのルールをどのように適用するか、というところですが、通常のセットアップではInit containerがSidecar proxyと共にアプリケーションのPodへInjectされて利用されます。このInit containerはiptablesを利用するため、NET_ADMIN capabilityが許可されている特権コンテナ(privileged, 要はroot権限)として設定される必要があります。しかし、特権コンテナを許可してしまうと、アプリケーションのすぐ横にセキュリティレベルの弱いコンテナが配置されることになりますし、特権コンテナ起動が許可されているサービスアカウントを流用して他の悪意のある特権コンテナを起動していろいろできてしまったりするので回避したいところです。そこで利用されるのがIstio CNIというCNIプラグインです。Istio CNIでは特権Init contaienrではなくCNIの仕組み内からiptablesのルール適用を行っています。

github.com

これがOpenShift 4.2上でどのように構成されているか見ていきたいと思います。この例ではtest-istioというプロジェクトを対象に見ていきます。

OpenShift Service MeshではServiceMeshMemberRollsというリソースにIstioを使うプロジェクトを記述するとセットアップが実行されます。

$ oc get -n istio-system servicemeshmemberrolls.maistra.io
NAME      MEMBERS
default   [knative-serving test-knative test-istio]

OpenShift 4ではmultus-cniというCNIプラグインを柔軟に選択できるCNIメタプラグインが標準となっており、上記設定を行うとMultusのNetworkAttachmentDefinitionというリソースがプロジェクトに作成され、istio-cniが有効化されます。NetworkAttachmentDefinitionの中身は利用するCNIの名前だけ指定されているものです。

$ oc get network-attachment-definitions.k8s.cni.cncf.io --all-namespaces 
NAMESPACE         NAME        AGE
knative-serving   istio-cni   23m
test-istio        istio-cni   23m
test-knative      istio-cni   32d

$ oc get -n test-istio network-attachment-definitions.k8s.cni.cncf.io istio-cni -o yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  generation: 1
  name: istio-cni
  namespace: test-istio

この設定はどこに紐づいているかというと、OpenShift Service Meshに含まれるDaemonSetが各ノードのmultus設定ディレクトリにCNI設定ファイルを配置していて、その名前を指定しています。

$ oc set volumes -n openshift-operators ds/istio-node
daemonsets/istio-node
  host path /opt/multus/bin as cni-bin-dir
    mounted at /host/opt/cni/bin
  host path /etc/cni as etc-cni-dir
    mounted at /host/etc/cni/

このDaemonSetによって各ホストに以下のファイル群が配置されています。

/etc/cni/multus/net.d/istio-cni.conf
/etc/cni/multus/net.d/istio-cni.kubeconfig
/opt/cni/bin/istio-cni
/opt/cni/bin/istio-iptables.sh

実際のCNI設定内容は以下のようになっています。

$ oc debug node/node01
# chroot /host
# cat /etc/cni/multus/net.d/istio-cni.conf
{
  "cniVersion": "0.3.0",
  "name": "istio-cni",
  "type": "istio-cni",
  "log_level": "info",
  "kubernetes": {
      "kubeconfig": "/etc/cni/multus/net.d/istio-cni.kubeconfig",
      "cni_bin_dir": "/opt/multus/bin",
      "iptables_script": "istio-iptables.sh",
      "exclude_namespaces": [ "openshift-operators" ]
  }
}

OpenShift Service Meshでは、このようにDaemonSetでMultusにistio-cni設定を配置、MultusのNetworkAttachmentDefinitionで有効化するという仕組みを利用して特権コンテナを利用しない、より安全なIstioのセットアップを実現しています。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。