内容は随時更新していきます。
ClusterProfile
ClusterProfileの概要
ClusterProfileは、Sveltosシステムにおいて複数のKubernetesクラスターにアドオンをデプロイするための主要なカスタムリソースです。ClusterProfileを使用することで、管理クラスターから複数のワークロードクラスターに対して一貫した設定を適用できます。
ClusterProfileの基本概念
ClusterProfileはクラスタースコープのリソースで、以下の主要な機能を提供します:
- クラスター選択: ラベルセレクターを使用して、設定を適用する対象クラスターを選択します
- アドオン定義: 選択したクラスターにデプロイするリソース(Helmチャート、Kubernetesリソース、Kustomizeリソース)を定義します
- 同期モード: リソースの適用方法(一度のみ、継続的、ドリフト検出付き継続的、ドライラン)を指定します
ClusterProfileの実装例1
以下は、本番環境(env: fvラベルを持つ)のすべてのクラスターにKyvernoをデプロイする例です:
# ClusterProfile定義
apiVersion: config.projectsveltos.io/v1beta1
kind: ClusterProfile
metadata:
name: deploy-kyverno
spec:
clusterSelector:
matchLabels:
env: fv
syncMode: Continuous
helmCharts:
- repositoryURL: https://kyverno.github.io/kyverno/
repositoryName: kyverno
chartName: kyverno/kyverno
chartVersion: v3.3.3
releaseName: kyverno-latest
releaseNamespace: kyverno
helmChartAction: Install
policyRefs:
- name: disallow-latest
namespace: default
kind: ConfigMap
patches:
- target:
group: apps
version: v1
kind: Deployment
name: ".*"
patch: |
- op: add
path: /metadata/labels/environment
value: production
引用: Post Renderer Patches - Projectsveltos Documentation
ClusterProfileの実装例2
以下は、 karpenter: enabled
ラベルを持つすべてのクラスターにKarpenterのdefault NodePoolとEC2NodeClassをデプロイする例です:
apiVersion: config.projectsveltos.io/v1beta1
kind: ClusterProfile
metadata:
name: karpenter-deployment
spec:
clusterSelector:
matchLabels:
karpenter: enabled
syncMode: ContinuousWithDriftDetection
policyRefs:
- name: karpenter-resources
namespace: "{{ .Cluster.metadata.namespace }}"
kind: ConfigMap
templateResourceRefs:
- resource:
apiVersion: v1
kind: ConfigMap
name: cluster-config
namespace: "{{ .Cluster.metadata.namespace }}"
identifier: ClusterConfig
---
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-resources
namespace: default
annotations:
policy.projectsveltos.io/template: "ok"
data:
nodepool.yaml: |
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
ec2nodeclass.yaml: |
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
kubelet:
podsPerCore: 2
maxPods: {{ if eq .ClusterConfig.data.environment "production" }}20{{ else }}10{{ end }}
systemReserved:
cpu: 100m
memory: 100Mi
ephemeral-storage: 1Gi
kubeReserved:
cpu: 200m
memory: 100Mi
ephemeral-storage: 3Gi
evictionHard:
memory.available: 5%
nodefs.available: 10%
nodefs.inodesFree: 10%
evictionSoft:
memory.available: 500Mi
nodefs.available: 15%
nodefs.inodesFree: 15%
evictionSoftGracePeriod:
memory.available: 1m
nodefs.available: 1m30s
nodefs.inodesFree: 2m
evictionMaxPodGracePeriod: 60
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
cpuCFSQuota: true
clusterDNS: ["10.0.1.100"]
amiFamily: AL2
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "{{ .Cluster.metadata.name }}"
environment: {{ .ClusterConfig.data.environment }}
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "{{ .Cluster.metadata.name }}"
environment: {{ .ClusterConfig.data.environment }}
role: "KarpenterNodeRole-{{ .Cluster.metadata.name }}"
instanceProfile: "KarpenterNodeInstanceProfile-{{ .Cluster.metadata.name }}"
amiSelectorTerms:
- tags:
karpenter.sh/discovery: "{{ .Cluster.metadata.name }}"
environment: {{ .ClusterConfig.data.environment }}
tags:
team: {{ .ClusterConfig.data.team }}
app: {{ .ClusterConfig.data.application }}
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 1
httpTokens: required
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: {{ if eq .ClusterConfig.data.environment "production" }}100Gi{{ else }}50Gi{{ end }}
volumeType: gp3
iops: {{ if eq .ClusterConfig.data.environment "production" }}10000{{ else }}3000{{ end }}
encrypted: true
deleteOnTermination: true
templateResourceRefsで参照されているClusterConfigの例は以下の通りです。
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-config
namespace: default
data:
environment: "production"
team: "platform-team"
application: "karpenter-autoscaler"
region: "us-west-2"
clusterType: "eks"
nodeInstanceType: "m5.xlarge"
minNodes: "3"
maxNodes: "10"
diskSize: "100"
kubernetesVersion: "1.28"
enableSpotInstances: "true"
enableGPUNodes: "false"
参考1: NodeClasses | Karpenter
参考2: Templates - Projectsveltos Documentation
Kustomizeを使用した例
Kustomizeリソースを使用する場合の例:
apiVersion: config.projectsveltos.io/v1beta1
kind: ClusterProfile
metadata:
name: hello-world
spec:
clusterSelector:
matchLabels:
env: fv
syncMode: Continuous
kustomizationRefs:
- namespace: flux2
name: flux2
kind: GitRepository
path: ./helloWorld/
targetNamespace: eng
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: flux2
namespace: flux2
spec:
interval: 1m0s
ref:
branch: main
timeout: 60s
url: ssh://git@github.com/gianlucam76/kustomize
同期モードの種類
ClusterProfileは以下の同期モードをサポートしています:
- OneTime: クラスター初期設定時に一度だけリソースをデプロイします。CNIプラグインなどの重要なインフラコンポーネントの初期デプロイに適しています。
- Continuous: ClusterProfileの変更を継続的に監視し、マッチするクラスターに自動的に適用します。複数クラスターの一貫性を維持するのに役立ちます。
- ContinuousWithDriftDetection: 継続的な同期に加えて、管理クラスターで定義された望ましい状態と実際のクラスター状態の間のドリフト(構成の乖離)を検出し、自動的に修正します。
- DryRun: 実際の変更を行わずにデプロイアクションをシミュレートします。テストや検証に役立ちます。
構成ドリフト検出
ContinuousWithDriftDetectionモードを使用すると、Sveltosは管理クラスターで定義された望ましい状態と実際のクラスター状態の間のドリフトを自動的に検出し、修正できます。 README.md:130-137
Subresources
projectsveltos.io/subresources
annotationを付けるとstatus等のsubresourcesも合わせて更新する事ができます.
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
projectsveltos.io/subresources: status
name: load-balancer-service
namespace: default
data:
service.yaml: |
apiVersion: v1
kind: Service
metadata:
name: sveltos-subresource
namespace: default
spec:
selector:
app: foo
ports:
- name: my-port
port: 443
protocol: TCP
targetPort: 1032
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 1.1.1.1
既存リソースの編集
以下のリソースがあるとします.
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
labels:
apps: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 1
EOF
以下のClusterProfileでそのリソースを編集することが可能です。
apiVersion: config.projectsveltos.io/v1beta1
kind: ClusterProfile
metadata:
name: deploy-resources
spec:
clusterSelector:
matchLabels:
env: production
templateResourceRefs:
- resource:
apiVersion: apps/v1
kind: Deployment
name: nginx-deployment
namespace: default
identifier: NginxDeployment
policyRefs:
- kind: ConfigMap
name: info
namespace: default
---
apiVersion: v1
kind: ConfigMap
metadata:
name: info
namespace: default
annotations:
projectsveltos.io/template: "true" # add annotation to indicate Sveltos content is a template
data:
secret.yaml: |
{{ $depl := (getResource "NginxDeployment") }}
{{ $depl := (chainSetField $depl "spec.replicas" (int64 1) ) }}
{{ $depl := (chainSetField $depl "metadata.namespace" .Cluster.metadata.namespace ) }}
{{ $depl := (chainSetField $depl "spec.template.spec.serviceAccountName" "default" ) }}
{{ $depl := (chainSetField $depl "spec.paused" true ) }}
{{ toYaml $depl }}
参考: Resource Manipulating Functions - Examples - Projectsveltos Documentation
ClusterProfileの動作の仕組み
ClusterProfileが作成または更新されると、以下のプロセスが実行されます:
- ClusterProfileReconcilerがClusterProfileを監視し、マッチするクラスターを選択します
- 各マッチするクラスターに対してClusterSummaryリソースを作成します
- デプロイ状態がClusterSummaryのステータスに反映されます
Event Manager
EventSource/EventTriggerの概要
ProjectsveltosのEventTriggerは、クラスターで発生したイベントに基づいてリソースを自動的に作成するための機能です。発生したイベントを表現するリソースはEventSourceです。以下に、シンプルなEventSource/EventTriggerの実装例を示します。
EventSource/EventTriggerの実装例1
以下はサービスがあったらNetworkPolicyを自動で作成する例です
---
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventSource
metadata:
name: sveltos-service
spec:
collectResources: true
resourceSelectors:
- group: ""
version: "v1"
kind: "Service"
labelFilters:
- key: sveltos
operation: Equal
value: fv
---
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventTrigger
metadata:
name: service-network-policy
spec:
sourceClusterSelector:
matchLabels:
env: fv
eventSourceName: sveltos-service
oneForEvent: true
policyRefs:
- name: network-policy
namespace: default
kind: ConfigMap
---
apiVersion: v1
kind: ConfigMap
metadata:
name: network-policy
namespace: default
annotations:
projectsveltos.io/instantiate: ok # this annotation is what tells Sveltos to instantiate this ConfigMap
data:
networkpolicy.yaml: |
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: front-{{ .Resource.metadata.name }}
namespace: {{ .Resource.metadata.namespace }}
spec:
podSelector:
matchLabels:
{{ range $key, $value := .Resource.spec.selector }}
{{ $key }}: {{ $value }}
{{ end }}
ingress:
- from:
- podSelector:
matchLabels:
app: internal
ports:
{{ range $port := .Resource.spec.ports }}
- port: {{ $port.port }}
{{ end }}
EventSource/EventTriggerの実装例2
以下は先ほどと同じサービスがあったらNetworkPolicyを自動で作成する例です。
ただし、ラベル sveltos: fv
がついているServiceのみを対象としています。
---
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventSource
metadata:
name: sveltos-service
spec:
collectResources: true
resourceSelectors:
- group: ""
version: "v1"
kind: "Service"
evaluate: |
function evaluate()
hs = {}
hs.matching = false
hs.message = ""
if obj.metadata.labels ~= nil then
for key, value in pairs(obj.metadata.labels) do
if key == "sveltos" then
if value == "fv" then
hs.matching = true
end
end
end
end
return hs
end
---
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventTrigger
metadata:
name: service-network-policy
spec:
sourceClusterSelector:
matchLabels:
env: fv
eventSourceName: sveltos-service
oneForEvent: true
policyRefs:
- name: network-policy
namespace: default
kind: ConfigMap
---
apiVersion: v1
kind: ConfigMap
metadata:
name: network-policy
namespace: default
annotations:
projectsveltos.io/instantiate: ok # this annotation is what tells Sveltos to instantiate this ConfigMap
data:
networkpolicy.yaml: |
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: front-{{ .Resource.metadata.name }}
namespace: {{ .Resource.metadata.namespace }}
spec:
podSelector:
matchLabels:
{{ range $key, $value := .Resource.spec.selector }}
{{ $key }}: {{ $value }}
{{ end }}
ingress:
- from:
- podSelector:
matchLabels:
app: internal
ports:
{{ range $port := .Resource.spec.ports }}
- port: {{ $port.port }}
{{ end }}
EventSourceの実装例3
異なる種類のリソースをまとめて調べる例です。
以下は 対応する Deployment が存在しない HPA を検出する EventSource です。
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventSource
metadata:
name: sveltos-service
spec:
collectResources: true
resourceSelectors:
- group: "apps"
version: "v1"
kind: "Deployment"
- kind: HorizontalPodAutoscaler
group: "autoscaling"
version: v2
aggregatedSelection: |
function getKey(namespace, name)
return namespace .. ":" .. name
end
function evaluate()
local hs = {}
hs.message = ""
local deployments = {}
local autoscalers = {}
local deploymentsWithNoAutoscaler = {}
for _, resource in ipairs(resources) do
local kind = resource.kind
if kind == "Deployment" then
key = getKey(resource.metadata.namespace, resource.metadata.name)
deployments[key] = true
elseif kind == "HorizontalPodAutoscaler" then
table.insert(autoscalers, resource)
end
end
-- Check for each horizontalPodAutoscaler if there is a matching Deployment
for _,hpa in ipairs(autoscalers) do
key = getKey(hpa.metadata.namespace, hpa.spec.scaleTargetRef.name)
if hpa.spec.scaleTargetRef.kind == "Deployment" then
if not deployments[key] then
table.insert(unusedAutoscalers, hpa)
end
end
end
if #unusedAutoscalers > 0 then
hs.resources = unusedAutoscalers
end
return hs
end
Classifier
Classifierの概要
Classifierは、Kubernetesクラスターの状態に基づいてクラスターを分類し、ラベルを付与するコンポーネントです。このラベル付けにより、クラスターは特定のClusterProfileにマッチするようになり、それに応じてアドオンやアプリケーションが自動的にデプロイされます。
Classifierの主な機能
Classifierは以下の基準に基づいてクラスターを分類できます:
- Kubernetesバージョン
- クラスター内にデプロイされているリソース
- Luaスクリプトによる評価
Classifierの動作の仕組み
- クラスターの状態の評価: Classifierはクラスターの状態(Kubernetesバージョンやデプロイされたリソースなど)を評価します
- マッチング: 定義された条件にクラスターがマッチする場合、ClassifierReportが生成されます
- ラベル付け: マッチしたクラスターに対して、Classifierで定義されたラベルが適用されます
- ClusterProfileの適用: ラベル付けされたクラスターは、そのラベルに基づいて特定のClusterProfileにマッチするようになります
- アドオンとアプリケーションのデプロイ: マッチしたClusterProfileに基づいて、アドオンやアプリケーションがクラスターにデプロイされます classifier_controller.go:445-463 classifier_controller.go:538-563
Classifierの実装例1
Kubernetesバージョンに基づくクラスターの分類.
例えば、Kubernetesバージョンが1.24.xのクラスターを分類し、特定のラベルを付与するClassifierを作成できます:
apiVersion: lib.projectsveltos.io/v1beta1
kind: Classifier
metadata:
name: kubernetes-v1.24
spec:
classifierLabels:
- key: k8s-version
value: v1.24
kubernetesVersionConstraints:
- comparison: GreaterThanOrEqualTo
version: 1.24.0
- comparison: LessThan
version: 1.25.0
Kubernetesバージョンに基づくアドオンの自動アップグレード
Classifierを使用して、クラスターのKubernetesバージョンが更新されたときに自動的にアドオンをアップグレードすることができます。例えば:
- Kubernetes v1.24.xのクラスターには「gatekeeper: v3-9」というラベルを付与
- Kubernetes v1.25.x以上のクラスターには「gatekeeper: v3-10」というラベルを付与
これにより、クラスターがKubernetes v1.24.xからv1.25.xにアップグレードされると、Gatekeeperも自動的に3.9.0から3.10.0にアップグレードされます。
Classifierの制限事項
マネージドクラスターとマネジメントクラスターの関係
質問にあった「マネジメントクラスター上のリソースに基づいてマネージドクラスターにラベルを付与できるか?」という点については、Classifierはマネージドクラスター自体の状態に基づいてのみラベルを付与します。マネジメントクラスター上のリソース(例:KeptnMetric)に基づいてマネージドクラスターにラベルを付与することはできません。
このようなユースケースには、Sveltosのイベントフレームワークを使用することが推奨されています。
Classifierの技術的な実装
Classifierは以下のコンポーネントで構成されています:
- ClassifierReconciler: Classifier CRの調整を担当するコントローラー
- ClassifierReport: クラスターがClassifierの条件にマッチするかどうかを報告するCR
- KeyManager: ラベルの管理と競合解決を担当するコンポーネント
デプロイメントモード
Classifierは以下の2つのモードで動作します:
- AgentInMgmtCluster (Agentless): マネジメントクラスターでエージェントが実行され、マネージドクラスターを監視
- Agent in Managed Clusters: 各マネージドクラスターでエージェントが実行され、自身の状態を報告
レポートモード
ClassifierReportの収集方法も2つのモードがあります:
- CollectFromManagementCluster: マネジメントクラスターが定期的にマネージドクラスターからレポートを収集
- AgentSendReportsNoGateway: マネージドクラスターのエージェントがレポートを直接マネジメントクラスターに送信
まとめ
Sveltos Classifierは、クラスターの状態に基づいて動的にラベルを付与し、それによってClusterProfileとのマッチングを可能にする強力なツールです。特にKubernetesバージョンのアップグレードに伴うアドオンの自動アップグレードなど、クラスター管理の自動化に役立ちます。
ただし、マネジメントクラスター上のリソースに基づいてマネージドクラスターにラベルを付与することはできないという制限があります。このようなユースケースには、Sveltosのイベントフレームワークを使用することが推奨されています。
Q&A
Q1: Sveltos Agentのdeploymentを手動で削除した場合、自動的に回復しますか?
A1: いいえ、Sveltos Agentのdeploymentを手動で削除しても自動的には回復しません。
Q2: Sveltos Agentを回復するにはどうすればよいですか?
Sveltos AgentはClassifier Managerが管理しているため、クラスタに対応するClassifierリソースを再作成してClassifier Managerを再起動すればSveltos Agentが再生成されます。