k8s k3s のセキュリティ強化について
公開: 2023年04月04日
k8s k3s のセキュリティ強化について
目次
k8s k3s のセキュリティ
Kubernetesには様々な機能があり、セキュリティ対策が必要だ。 最近はエッジコンピューティングとして用いられる軽量k8sであるk3sもある。
クラウド上のEKSはAWSがマネジメントしてくれるし、ELB等の下や隔離網にデプロイされるのでセキュリティは高い状態が保たれるが、 オンプレk8sの場合はネットワークの疎通はあるし、アプリ同梱型であればアプリの動作ホスト内でk8sが動作することになる。
k3sはエッジコンピューティングとして利用が期待されていて、別拠点のk3sとクラスタを組むことになるのでセキュリティリスクが想定される。 k8s/k3sはクラスタ間通信としてvxlanがCNI経由で処理されるので、これが漏れるとクラスタないを行き来できてしまう。
クラスタ内通信の制御方法としてNetwork Policyがあり、
podSelector
を使ったPod間の通信の制御やingress
egress
によるipBlcokのCIDR指定のIPフィルタリングも可能。
エッジ端末としてk3sを動作させる場合はagentモードで動作させることになるが、この状態におけるセキュリティを考えたい。
検討項目
k3sにはCIS セキュリティ強化ガイドhardening-guideがある。
1. k3s の管理範囲
k3sは 動作ホストのオペレーティングシステムの設定を変更しない。 このため、ホストレベルでの変更が必要な操作は手動でやる必要がある。
2. Host-level Requirements
以下のカーネルパラメータが設定されていること
protect-kernel-defaults
以下でホストに設定する。
/etc/sysctl.d/90-kubelet.conf
適用 ⇒ sysctl -p /etc/sysctl.d/90-kubelet.conf
vm.panic_on_oom=0
vm.overcommit_memory=1
kernel.panic=10
kernel.panic_on_oops=1
kernel.keys.root_maxbytes=25000000
3. Kubernetes Runtime Requirements
CIS ベンチマークに準拠するためのランタイム要件は、ポッド セキュリティ (PSP または PSA 経由)、ネットワーク ポリシー、および API サーバー監査ログに集中している。
デフォルトでは、K3s にはポッドセキュリティまたはネットワーク ポリシーは含まれない。 ただし、K3s には、ネットワークポリシーが作成されている場合に適用するコントローラが同梱されている。 K3s は既定で監査を有効にしないため、監査ログの構成と監査ポリシーを手動で作成する必要がある。 デフォルトでは、K3s はとアドミッション コントローラーの両方がNodeRestriction有効になっている状態で実行される。
4. Pod Security
K3s v1.25 以降では、ポッド セキュリティを制御するためのポッド セキュリティ アドミッション (PSA)がサポートされている。
CIS では、すべての名前空間に、名前空間とポッドへのトラフィックを合理的に制限するネットワーク ポリシーが適用されている必要がある。
ネットワーク ポリシーは、起動時に自動的に展開されるディレクトリに配置する必要がある。
/var/lib/rancher/k3s/server/manifests
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: intra-namespace
namespace: kube-system
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-system
この適用された制限によって、DNSもブロックされてしまうようで、DNSを許可する場合は以下。
単にingressでkube-dns
に対してport53をTCP/UDP許可するだけのもの。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-network-dns-policy
namespace: <NAMESPACE>
spec:
ingress:
- ports:
- port: 53
protocol: TCP
- port: 53
protocol: UDP
podSelector:
matchLabels:
k8s-app: kube-dns
policyTypes:
- Ingress
5. コントロールプレーン(Server)がデフォルトで与えられるオプション
k3sのServerの起動オプションは以下がデフォルトで与えれるようだ。
apiserver
kube-apiserver
--advertise-port=6443
--allow-privileged=true
--anonymous-auth=false # 1.2.1
--api-audiences=unknown
--authorization-mode=Node,RBAC
--bind-address=127.0.0.1
--cert-dir=/var/lib/rancher/k3s/server/tls/temporary-certs
--client-ca-file=/var/lib/rancher/k3s/server/tls/client-ca.crt # 1.2.31
--enable-admission-plugins=NodeRestriction,PodSecurityPolicy # 1.2.17
--etcd-cafile=/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt # 1.2.32
--etcd-certfile=/var/lib/rancher/k3s/server/tls/etcd/client.crt # 1.2.29
--etcd-keyfile=/var/lib/rancher/k3s/server/tls/etcd/client.key # 1.2.29
--etcd-servers=https://127.0.0.1:2379
--insecure-port=0 # 1.2.19
--kubelet-certificate-authority=/var/lib/rancher/k3s/server/tls/server-ca.crt
--kubelet-client-certificate=/var/lib/rancher/k3s/server/tls/client-kube-apiserver.crt
--kubelet-client-key=/var/lib/rancher/k3s/server/tls/client-kube-apiserver.key
--profiling=false # 1.2.21
--proxy-client-cert-file=/var/lib/rancher/k3s/server/tls/client-auth-proxy.crt
--proxy-client-key-file=/var/lib/rancher/k3s/server/tls/client-auth-proxy.key
--requestheader-allowed-names=system:auth-proxy
--requestheader-client-ca-file=/var/lib/rancher/k3s/server/tls/request-header-ca.crt
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--secure-port=6444 # 1.2.20
--service-account-issuer=k3s
--service-account-key-file=/var/lib/rancher/k3s/server/tls/service.key # 1.2.28
--service-account-signing-key-file=/var/lib/rancher/k3s/server/tls/service.key
--service-cluster-ip-range=10.43.0.0/16
--storage-backend=etcd3
--tls-cert-file=/var/lib/rancher/k3s/server/tls/serving-kube-apiserver.crt # 1.2.30
--tls-private-key-file=/var/lib/rancher/k3s/server/tls/serving-kube-apiserver.key # 1.2.30
--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
advertise-portは6443でallow-privileged=true。 etcdに関しては多分使われずSQLieのはず。
kube-controller-manager
kube-controller-managerのデフォルトパラメータ
kube-controller-manager
--address=127.0.0.1
--allocate-node-cidrs=true
--bind-address=127.0.0.1 # 1.3.7
--cluster-cidr=10.42.0.0/16
--cluster-signing-cert-file=/var/lib/rancher/k3s/server/tls/client-ca.crt
--cluster-signing-key-file=/var/lib/rancher/k3s/server/tls/client-ca.key
--kubeconfig=/var/lib/rancher/k3s/server/cred/controller.kubeconfig
--port=10252
--profiling=false # 1.3.2
--root-ca-file=/var/lib/rancher/k3s/server/tls/server-ca.crt # 1.3.5
--secure-port=0
--service-account-private-key-file=/var/lib/rancher/k3s/server/tls/service.key # 1.3.4
--use-service-account-credentials=true
まとめ
k3sのエッジ端末での動作におけるセキュリティを確認したが、 NetworkPolicyやPodSecurityPolicy(新PSA)による制御が可能なので、pod自体の心配はしなくて良い。
また、agent動作なのでkubeapiserverはないし、k8s自体に関与はできないので、他のクラスタノードへの影響もない。
なので、コントロールプレーンからJOBコンテナなんかをエッジのk3sで動作させるなんて用途はよさそうで、 ansibleタスクとの相性も良いし、daemonsetとして常駐サービスを後から稼働とかもできそう。