@rulebricks/cli 2.1.6 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/cluster-setup/aws/README.md +74 -0
- package/cluster-setup/aws/check-aws-access.sh +78 -0
- package/cluster-setup/aws/cluster.yaml +33 -0
- package/cluster-setup/azure/README.md +93 -0
- package/cluster-setup/azure/check-aks-prereqs.sh +96 -0
- package/cluster-setup/azure/main.bicep +282 -0
- package/cluster-setup/azure/main.parameters.json +21 -0
- package/cluster-setup/gcp/README.md +172 -0
- package/cluster-setup/gcp/check-gke-prereqs.sh +98 -0
- package/dist/commands/init.js +9 -2
- package/dist/components/Wizard/WizardContext.d.ts +27 -3
- package/dist/components/Wizard/WizardContext.js +95 -2
- package/dist/components/Wizard/steps/CloudProviderStep.js +7 -2
- package/dist/components/Wizard/steps/FeatureConfigStep.js +407 -10
- package/dist/components/Wizard/steps/ReviewStep.js +7 -2
- package/dist/lib/helmValues.js +227 -22
- package/dist/lib/kubernetes.d.ts +7 -1
- package/dist/lib/kubernetes.js +59 -0
- package/dist/types/index.d.ts +367 -6
- package/dist/types/index.js +46 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -27,6 +27,32 @@ Finally, you will need to have the following tools installed and ready on your m
|
|
|
27
27
|
- **Terraform** >= 1.0 (for infrastructure provisioning)
|
|
28
28
|
- Cloud CLI (`aws`, `gcloud`, or `az`) configured for your provider
|
|
29
29
|
|
|
30
|
+
## Cluster Setup
|
|
31
|
+
|
|
32
|
+
If you want to create the Kubernetes cluster yourself, use the resources in `cluster-setup/` before running the CLI wizard. These files provide minimum compatible AWS, Azure, and GCP cluster setup guidance plus optional access checks. Monitoring destinations are configured later by the CLI wizard and Helm values, not by these cluster setup files.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# AWS: optional access check, then create EKS with eksctl
|
|
36
|
+
AWS_REGION=us-east-1 bash cluster-setup/aws/check-aws-access.sh
|
|
37
|
+
cd cluster-setup/aws && eksctl create cluster -f cluster.yaml
|
|
38
|
+
|
|
39
|
+
# Azure: optional access check, then deploy AKS with Bicep
|
|
40
|
+
az login
|
|
41
|
+
az account set --subscription <subscription-id>
|
|
42
|
+
AZURE_LOCATION=eastus bash cluster-setup/azure/check-aks-prereqs.sh
|
|
43
|
+
az group create --name rulebricks-rg --location eastus
|
|
44
|
+
az deployment group create \
|
|
45
|
+
--resource-group rulebricks-rg \
|
|
46
|
+
--template-file cluster-setup/azure/main.bicep \
|
|
47
|
+
--parameters @cluster-setup/azure/main.parameters.json
|
|
48
|
+
|
|
49
|
+
# GCP: optional access check, then create GKE with gcloud
|
|
50
|
+
GCP_REGION=us-central1 bash cluster-setup/gcp/check-gke-prereqs.sh
|
|
51
|
+
# Follow cluster-setup/gcp/README.md for the gcloud create commands.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
After the cluster exists, update kubeconfig, then run `rulebricks init` and choose **Use existing Kubernetes cluster**. The existing Terraform provisioning path remains available, but native cloud setup is the clearest path when you want to own the cluster directly.
|
|
55
|
+
|
|
30
56
|
## Quick Start
|
|
31
57
|
|
|
32
58
|
```bash
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# AWS Cluster Setup
|
|
2
|
+
|
|
3
|
+
Use these files to create a minimum EKS cluster that can run Rulebricks without using the Rulebricks CLI Terraform flow.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
- `cluster.yaml` is the minimum compatible `eksctl` cluster config, using ARM64 managed nodes and EBS CSI support.
|
|
8
|
+
- `check-aws-access.sh` verifies AWS identity, common EKS/EC2/IAM permissions, quota, `eksctl`, `kubectl`, and Helm.
|
|
9
|
+
|
|
10
|
+
## Core Cluster Parameters
|
|
11
|
+
|
|
12
|
+
- Cluster name: `rulebricks-cluster` (`cluster.yaml` -> `metadata.name`)
|
|
13
|
+
- Region: `us-east-1` (`cluster.yaml` -> `metadata.region`)
|
|
14
|
+
- Kubernetes version: `1.34` (`cluster.yaml` -> `metadata.version`)
|
|
15
|
+
- Node count: `4` (`cluster.yaml` -> `managedNodeGroups[0].desiredCapacity`)
|
|
16
|
+
- Instance type: `c8g.large` (`cluster.yaml` -> `managedNodeGroups[0].instanceType`)
|
|
17
|
+
- Disk size (GB): `50` (`cluster.yaml` -> `managedNodeGroups[0].volumeSize`)
|
|
18
|
+
- Disk type: `gp3` (`cluster.yaml` -> `managedNodeGroups[0].volumeType`)
|
|
19
|
+
|
|
20
|
+
## Check Access
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
AWS_REGION=us-east-1 bash check-aws-access.sh
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Create The Cluster
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
eksctl create cluster -f cluster.yaml
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`eksctl` updates kubeconfig automatically. To refresh it manually:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
aws eks update-kubeconfig --name rulebricks-cluster --region us-east-1
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use `rulebricks init` with **Use existing Kubernetes cluster** after kubeconfig works.
|
|
39
|
+
|
|
40
|
+
## Optional Identity Setup
|
|
41
|
+
|
|
42
|
+
If you use S3 decision-log export or AWS Managed Prometheus remote write, create IAM roles for the Kubernetes service accounts rendered by the CLI:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
NAMESPACE=rulebricks-demo
|
|
46
|
+
CLUSTER=rulebricks-cluster
|
|
47
|
+
REGION=us-east-1
|
|
48
|
+
ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
|
|
49
|
+
|
|
50
|
+
eksctl utils associate-iam-oidc-provider \
|
|
51
|
+
--cluster "$CLUSTER" \
|
|
52
|
+
--region "$REGION" \
|
|
53
|
+
--approve
|
|
54
|
+
|
|
55
|
+
eksctl create iamserviceaccount \
|
|
56
|
+
--cluster "$CLUSTER" \
|
|
57
|
+
--region "$REGION" \
|
|
58
|
+
--namespace "$NAMESPACE" \
|
|
59
|
+
--name vector \
|
|
60
|
+
--attach-policy-arn arn:aws:iam::"$ACCOUNT_ID":policy/<vector-s3-policy> \
|
|
61
|
+
--role-name rulebricks-vector \
|
|
62
|
+
--approve
|
|
63
|
+
|
|
64
|
+
eksctl create iamserviceaccount \
|
|
65
|
+
--cluster "$CLUSTER" \
|
|
66
|
+
--region "$REGION" \
|
|
67
|
+
--namespace "$NAMESPACE" \
|
|
68
|
+
--name prometheus \
|
|
69
|
+
--attach-policy-arn arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess \
|
|
70
|
+
--role-name rulebricks-prometheus \
|
|
71
|
+
--approve
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Enter the created role ARNs when prompted by the CLI.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-us-east-1}}"
|
|
5
|
+
REQUIRED_VCPU=8
|
|
6
|
+
|
|
7
|
+
require_cmd() {
|
|
8
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
9
|
+
echo "Missing required command: $1" >&2
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
check_aws() {
|
|
15
|
+
echo "Checking AWS identity..."
|
|
16
|
+
aws sts get-caller-identity --output table
|
|
17
|
+
echo
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
check_permission() {
|
|
21
|
+
local label="$1"
|
|
22
|
+
shift
|
|
23
|
+
if "$@" >/dev/null 2>&1; then
|
|
24
|
+
echo "OK: $label"
|
|
25
|
+
else
|
|
26
|
+
echo "WARN: Could not verify $label"
|
|
27
|
+
echo " Command failed: $*"
|
|
28
|
+
fi
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
check_quota() {
|
|
32
|
+
echo "Checking regional on-demand vCPU quota in $REGION..."
|
|
33
|
+
local quota
|
|
34
|
+
quota="$(aws service-quotas get-service-quota \
|
|
35
|
+
--service-code ec2 \
|
|
36
|
+
--quota-code L-1216C47A \
|
|
37
|
+
--region "$REGION" \
|
|
38
|
+
--query 'Quota.Value' \
|
|
39
|
+
--output text 2>/dev/null || true)"
|
|
40
|
+
|
|
41
|
+
if [[ -z "$quota" || "$quota" == "None" ]]; then
|
|
42
|
+
echo "WARN: Could not read EC2 on-demand vCPU quota."
|
|
43
|
+
return
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
local quota_int="${quota%.*}"
|
|
47
|
+
if (( quota_int < REQUIRED_VCPU )); then
|
|
48
|
+
echo "WARN: Quota may be too low: ${quota} vCPU available, ${REQUIRED_VCPU}+ recommended for the included cluster config."
|
|
49
|
+
else
|
|
50
|
+
echo "OK: EC2 on-demand vCPU quota is ${quota}."
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
require_cmd aws
|
|
55
|
+
require_cmd eksctl
|
|
56
|
+
require_cmd kubectl
|
|
57
|
+
require_cmd helm
|
|
58
|
+
|
|
59
|
+
echo "Rulebricks AWS access checks"
|
|
60
|
+
echo "Region: $REGION"
|
|
61
|
+
echo
|
|
62
|
+
|
|
63
|
+
check_aws
|
|
64
|
+
check_permission "EKS access" aws eks list-clusters --region "$REGION"
|
|
65
|
+
check_permission "EC2 VPC access" aws ec2 describe-vpcs --region "$REGION" --max-items 5
|
|
66
|
+
check_permission "IAM access" aws iam get-user
|
|
67
|
+
check_permission "ECR public image pull path" aws ecr-public describe-registries --region us-east-1
|
|
68
|
+
check_quota
|
|
69
|
+
|
|
70
|
+
echo
|
|
71
|
+
echo "Checking local Kubernetes tools..."
|
|
72
|
+
eksctl version >/dev/null
|
|
73
|
+
kubectl version --client=true >/dev/null
|
|
74
|
+
helm version >/dev/null
|
|
75
|
+
echo "OK: eksctl, kubectl, and Helm are installed."
|
|
76
|
+
|
|
77
|
+
echo
|
|
78
|
+
echo "AWS access checks completed. Warnings may require cloud-admin review before cluster creation."
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Minimum eksctl configuration for a Rulebricks EKS cluster.
|
|
2
|
+
# Core knobs: name, region, Kubernetes version, instance type, node count,
|
|
3
|
+
# disk size, and disk type.
|
|
4
|
+
# Nodes must be ARM based. Storage is required; customize Helm storage class
|
|
5
|
+
# values if you use a different CSI driver or StorageClass.
|
|
6
|
+
|
|
7
|
+
apiVersion: eksctl.io/v1alpha5
|
|
8
|
+
kind: ClusterConfig
|
|
9
|
+
|
|
10
|
+
metadata:
|
|
11
|
+
name: rulebricks-cluster
|
|
12
|
+
region: us-east-1
|
|
13
|
+
version: "1.34"
|
|
14
|
+
|
|
15
|
+
managedNodeGroups:
|
|
16
|
+
- name: standard-nodes
|
|
17
|
+
instanceType: c8g.large
|
|
18
|
+
desiredCapacity: 4
|
|
19
|
+
minSize: 4
|
|
20
|
+
maxSize: 4
|
|
21
|
+
volumeSize: 50
|
|
22
|
+
volumeType: gp3
|
|
23
|
+
amiFamily: AmazonLinux2023
|
|
24
|
+
iam:
|
|
25
|
+
withAddonPolicies:
|
|
26
|
+
ebs: true
|
|
27
|
+
albIngress: true
|
|
28
|
+
|
|
29
|
+
addons:
|
|
30
|
+
- name: vpc-cni
|
|
31
|
+
- name: coredns
|
|
32
|
+
- name: kube-proxy
|
|
33
|
+
- name: aws-ebs-csi-driver
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Azure Cluster Setup
|
|
2
|
+
|
|
3
|
+
Use these files to create a minimum AKS cluster that can run Rulebricks without using the Rulebricks CLI Terraform flow.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
- `main.bicep` creates a minimum compatible AKS cluster with ARM64 nodes, Azure CNI, Calico, Standard Load Balancer, Disk CSI, OIDC issuer, and Workload Identity.
|
|
8
|
+
- `main.parameters.json` is a sample Bicep parameter file.
|
|
9
|
+
- `check-aks-prereqs.sh` verifies Azure CLI login, subscription state, provider registration, selected-region quota, resource group access, `kubectl`, and Helm.
|
|
10
|
+
|
|
11
|
+
## Core Cluster Parameters
|
|
12
|
+
|
|
13
|
+
- Cluster name: `rulebricks-cluster` (`main.parameters.json` -> `clusterName`)
|
|
14
|
+
- Region: `eastus` (`main.parameters.json` -> `location`)
|
|
15
|
+
- Kubernetes version: `1.34` (`main.parameters.json` -> `kubernetesVersion`)
|
|
16
|
+
- Node count: `4` (`main.parameters.json` -> `nodeCount`)
|
|
17
|
+
- VM size: `Standard_D2ps_v5` (`main.parameters.json` -> `nodeVmSize`)
|
|
18
|
+
- Disk size (GB): `20` (`main.parameters.json` -> `osDiskSizeGB`)
|
|
19
|
+
- Disk type: `Managed` (`main.parameters.json` -> `osDiskType`)
|
|
20
|
+
|
|
21
|
+
## Parameter Groups
|
|
22
|
+
|
|
23
|
+
`main.parameters.json` keeps the core cluster shape first, followed by optional Rulebricks identity settings.
|
|
24
|
+
|
|
25
|
+
- Core cluster parameters: `clusterName`, `location`, `kubernetesVersion`, `nodeCount`, `nodeVmSize`, `osDiskSizeGB`, `osDiskType`.
|
|
26
|
+
- Rulebricks identity parameters: `rulebricksNamespace`, `vectorServiceAccountName`, `prometheusServiceAccountName`, `enableExternalDns`, `dnsZoneResourceGroup`, `enableBlobLogging`, `loggingStorageAccountName`.
|
|
27
|
+
|
|
28
|
+
## Check Access
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
az login
|
|
32
|
+
az account set --subscription <subscription-id>
|
|
33
|
+
AZURE_LOCATION=eastus bash check-aks-prereqs.sh
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If provider registration warnings appear, run the suggested `az provider register` commands and wait for registration to complete.
|
|
37
|
+
|
|
38
|
+
## Create The Cluster
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
az group create --name rulebricks-rg --location eastus
|
|
42
|
+
az deployment group create \
|
|
43
|
+
--resource-group rulebricks-rg \
|
|
44
|
+
--template-file main.bicep \
|
|
45
|
+
--parameters @main.parameters.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then configure kubeconfig:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
az aks get-credentials --name rulebricks-cluster --resource-group rulebricks-rg
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Use `rulebricks init` with **Use existing Kubernetes cluster** after kubeconfig works.
|
|
55
|
+
|
|
56
|
+
## Notes
|
|
57
|
+
|
|
58
|
+
- The template creates four `Standard_D2ps_v5` ARM64 nodes, matching the minimum CLI Terraform defaults.
|
|
59
|
+
- Set `rulebricksNamespace` in `main.parameters.json` to the namespace the CLI will use, usually `rulebricks-<deployment-name>`, before enabling Workload Identity integrations.
|
|
60
|
+
- Azure DNS and Blob role assignments are created in the deployment resource group. If your DNS zone or storage account lives elsewhere, have an Azure admin assign `DNS Zone Contributor` or `Storage Blob Data Contributor` to the emitted managed identity client ID.
|
|
61
|
+
|
|
62
|
+
The deployment outputs `vectorClientId` and `prometheusClientId`. Enter those client IDs in the CLI when configuring Azure Blob decision logs or Azure Monitor remote write with Workload Identity.
|
|
63
|
+
|
|
64
|
+
## Fallback Secret-Based Auth
|
|
65
|
+
|
|
66
|
+
If Workload Identity is not available, Azure Blob decision-log export can use a storage account connection string stored in the Rulebricks namespace:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
kubectl create namespace rulebricks-demo
|
|
70
|
+
kubectl create secret generic azure-blob-logs \
|
|
71
|
+
--namespace rulebricks-demo \
|
|
72
|
+
--from-literal=connection-string='<azure-storage-connection-string>'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
When prompted by the CLI, enter:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
azure-blob-logs:connection-string
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Azure Monitor remote write can also use OAuth client-secret auth as a fallback:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
kubectl create secret generic azure-monitor-oauth \
|
|
85
|
+
--namespace rulebricks-demo \
|
|
86
|
+
--from-literal=client-secret='<client-secret>'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
When prompted by the CLI, enter:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
azure-monitor-oauth:client-secret
|
|
93
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
LOCATION="${AZURE_LOCATION:-eastus}"
|
|
5
|
+
RESOURCE_GROUP="${AZURE_RESOURCE_GROUP:-}"
|
|
6
|
+
REQUIRED_VCPU=8
|
|
7
|
+
REQUIRED_PROVIDERS=(
|
|
8
|
+
Microsoft.ContainerService
|
|
9
|
+
Microsoft.Network
|
|
10
|
+
Microsoft.ManagedIdentity
|
|
11
|
+
Microsoft.Compute
|
|
12
|
+
Microsoft.Authorization
|
|
13
|
+
Microsoft.Storage
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
require_cmd() {
|
|
17
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
18
|
+
echo "Missing required command: $1" >&2
|
|
19
|
+
exit 1
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
check_provider() {
|
|
24
|
+
local provider="$1"
|
|
25
|
+
local state
|
|
26
|
+
state="$(az provider show --namespace "$provider" --query registrationState --output tsv 2>/dev/null || true)"
|
|
27
|
+
if [[ "$state" == "Registered" ]]; then
|
|
28
|
+
echo "OK: $provider is registered"
|
|
29
|
+
else
|
|
30
|
+
echo "WARN: $provider is $state. Run: az provider register --namespace $provider"
|
|
31
|
+
fi
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
check_quota() {
|
|
35
|
+
echo "Checking regional vCPU quota in $LOCATION..."
|
|
36
|
+
local usage
|
|
37
|
+
local limit
|
|
38
|
+
usage="$(az vm list-usage --location "$LOCATION" --query "[?name.value=='cores'].currentValue | [0]" --output tsv 2>/dev/null || true)"
|
|
39
|
+
limit="$(az vm list-usage --location "$LOCATION" --query "[?name.value=='cores'].limit | [0]" --output tsv 2>/dev/null || true)"
|
|
40
|
+
|
|
41
|
+
if [[ -z "$usage" || -z "$limit" ]]; then
|
|
42
|
+
echo "WARN: Could not read regional vCPU quota."
|
|
43
|
+
return
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
local available=$((limit - usage))
|
|
47
|
+
if (( available < REQUIRED_VCPU )); then
|
|
48
|
+
echo "WARN: ${available}/${limit} vCPUs available; ${REQUIRED_VCPU}+ recommended for the included cluster config."
|
|
49
|
+
else
|
|
50
|
+
echo "OK: ${available}/${limit} vCPUs available."
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
check_access() {
|
|
55
|
+
local label="$1"
|
|
56
|
+
shift
|
|
57
|
+
if "$@" >/dev/null 2>&1; then
|
|
58
|
+
echo "OK: $label"
|
|
59
|
+
else
|
|
60
|
+
echo "WARN: Could not verify $label"
|
|
61
|
+
echo " Command failed: $*"
|
|
62
|
+
fi
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
require_cmd az
|
|
66
|
+
require_cmd kubectl
|
|
67
|
+
require_cmd helm
|
|
68
|
+
|
|
69
|
+
echo "Rulebricks AKS prerequisite checks"
|
|
70
|
+
echo "Location: $LOCATION"
|
|
71
|
+
echo
|
|
72
|
+
|
|
73
|
+
echo "Checking Azure account..."
|
|
74
|
+
az account show --query "{name:name,id:id,state:state,tenantId:tenantId}" --output table
|
|
75
|
+
echo
|
|
76
|
+
|
|
77
|
+
for provider in "${REQUIRED_PROVIDERS[@]}"; do
|
|
78
|
+
check_provider "$provider"
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
echo
|
|
82
|
+
check_access "AKS list access" az aks list --output none
|
|
83
|
+
check_access "Subscription deployment read access" az deployment sub list --query "[0].name" --output tsv
|
|
84
|
+
if [[ -n "$RESOURCE_GROUP" ]]; then
|
|
85
|
+
check_access "Resource group access ($RESOURCE_GROUP)" az group show --name "$RESOURCE_GROUP"
|
|
86
|
+
fi
|
|
87
|
+
check_quota
|
|
88
|
+
|
|
89
|
+
echo
|
|
90
|
+
echo "Checking local Kubernetes tools..."
|
|
91
|
+
kubectl version --client=true >/dev/null
|
|
92
|
+
helm version >/dev/null
|
|
93
|
+
echo "OK: kubectl and Helm are installed."
|
|
94
|
+
|
|
95
|
+
echo
|
|
96
|
+
echo "AKS prerequisite checks completed. Warnings may require Azure admin review before cluster creation."
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
targetScope = 'resourceGroup'
|
|
2
|
+
|
|
3
|
+
@description('Name of the AKS cluster.')
|
|
4
|
+
param clusterName string = 'rulebricks-cluster'
|
|
5
|
+
|
|
6
|
+
@description('Azure region for all resources.')
|
|
7
|
+
param location string = resourceGroup().location
|
|
8
|
+
|
|
9
|
+
@description('AKS Kubernetes version.')
|
|
10
|
+
param kubernetesVersion string = '1.34'
|
|
11
|
+
|
|
12
|
+
@description('Number of nodes in the default node pool.')
|
|
13
|
+
param nodeCount int = 4
|
|
14
|
+
|
|
15
|
+
@description('VM size for the default node pool. ARM64 (Standard_*ps_*) recommended.')
|
|
16
|
+
param nodeVmSize string = 'Standard_D2ps_v5'
|
|
17
|
+
|
|
18
|
+
@description('OS disk size in GB for the default node pool.')
|
|
19
|
+
param osDiskSizeGB int = 20
|
|
20
|
+
|
|
21
|
+
@description('OS disk type for the default node pool.')
|
|
22
|
+
@allowed([
|
|
23
|
+
'Managed'
|
|
24
|
+
'Ephemeral'
|
|
25
|
+
])
|
|
26
|
+
param osDiskType string = 'Managed'
|
|
27
|
+
|
|
28
|
+
@description('Namespace where Rulebricks will be installed. CLI deployments usually use rulebricks-<deployment-name>.')
|
|
29
|
+
param rulebricksNamespace string = 'rulebricks'
|
|
30
|
+
|
|
31
|
+
@description('Kubernetes ServiceAccount name used by Vector.')
|
|
32
|
+
param vectorServiceAccountName string = 'vector'
|
|
33
|
+
|
|
34
|
+
@description('Kubernetes ServiceAccount name used by Prometheus.')
|
|
35
|
+
param prometheusServiceAccountName string = 'prometheus'
|
|
36
|
+
|
|
37
|
+
@description('Enable a user-assigned identity and federated credential for external-dns with Azure DNS.')
|
|
38
|
+
param enableExternalDns bool = false
|
|
39
|
+
|
|
40
|
+
@description('Resource group containing the Azure DNS zone. Required when enableExternalDns is true.')
|
|
41
|
+
param dnsZoneResourceGroup string = ''
|
|
42
|
+
|
|
43
|
+
@description('Enable a user-assigned identity and federated credential for Vector Azure Blob logging.')
|
|
44
|
+
param enableBlobLogging bool = false
|
|
45
|
+
|
|
46
|
+
@description('Existing Azure Storage account name for Vector logs.')
|
|
47
|
+
param loggingStorageAccountName string = ''
|
|
48
|
+
|
|
49
|
+
var networkContributorRoleId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
|
|
50
|
+
var dnsZoneContributorRoleId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')
|
|
51
|
+
var storageBlobDataContributorRoleId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
|
|
52
|
+
|
|
53
|
+
resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
|
|
54
|
+
name: '${clusterName}-vnet'
|
|
55
|
+
location: location
|
|
56
|
+
tags: {
|
|
57
|
+
Environment: 'rulebricks'
|
|
58
|
+
}
|
|
59
|
+
properties: {
|
|
60
|
+
addressSpace: {
|
|
61
|
+
addressPrefixes: [
|
|
62
|
+
'10.0.0.0/8'
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
subnets: [
|
|
66
|
+
{
|
|
67
|
+
name: 'aks-subnet'
|
|
68
|
+
properties: {
|
|
69
|
+
addressPrefix: '10.240.0.0/16'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
resource nsg 'Microsoft.Network/networkSecurityGroups@2023-11-01' = {
|
|
77
|
+
name: '${clusterName}-nsg'
|
|
78
|
+
location: location
|
|
79
|
+
tags: {
|
|
80
|
+
Environment: 'rulebricks'
|
|
81
|
+
}
|
|
82
|
+
properties: {
|
|
83
|
+
securityRules: [
|
|
84
|
+
{
|
|
85
|
+
name: 'AllowVNetInbound'
|
|
86
|
+
properties: {
|
|
87
|
+
priority: 100
|
|
88
|
+
direction: 'Inbound'
|
|
89
|
+
access: 'Allow'
|
|
90
|
+
protocol: '*'
|
|
91
|
+
sourcePortRange: '*'
|
|
92
|
+
destinationPortRange: '*'
|
|
93
|
+
sourceAddressPrefix: 'VirtualNetwork'
|
|
94
|
+
destinationAddressPrefix: 'VirtualNetwork'
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
{
|
|
98
|
+
name: 'AllowVNetOutbound'
|
|
99
|
+
properties: {
|
|
100
|
+
priority: 100
|
|
101
|
+
direction: 'Outbound'
|
|
102
|
+
access: 'Allow'
|
|
103
|
+
protocol: '*'
|
|
104
|
+
sourcePortRange: '*'
|
|
105
|
+
destinationPortRange: '*'
|
|
106
|
+
sourceAddressPrefix: 'VirtualNetwork'
|
|
107
|
+
destinationAddressPrefix: 'VirtualNetwork'
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = {
|
|
115
|
+
parent: vnet
|
|
116
|
+
name: 'aks-subnet'
|
|
117
|
+
properties: {
|
|
118
|
+
addressPrefix: '10.240.0.0/16'
|
|
119
|
+
networkSecurityGroup: {
|
|
120
|
+
id: nsg.id
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
resource aksIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
|
|
126
|
+
name: '${clusterName}-identity'
|
|
127
|
+
location: location
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
resource aksNetworkRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
|
|
131
|
+
name: guid(vnet.id, aksIdentity.id, 'Network Contributor')
|
|
132
|
+
scope: vnet
|
|
133
|
+
properties: {
|
|
134
|
+
roleDefinitionId: networkContributorRoleId
|
|
135
|
+
principalId: aksIdentity.properties.principalId
|
|
136
|
+
principalType: 'ServicePrincipal'
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
resource aks 'Microsoft.ContainerService/managedClusters@2024-05-01' = {
|
|
141
|
+
name: clusterName
|
|
142
|
+
location: location
|
|
143
|
+
tags: {
|
|
144
|
+
Environment: 'rulebricks'
|
|
145
|
+
}
|
|
146
|
+
identity: {
|
|
147
|
+
type: 'UserAssigned'
|
|
148
|
+
userAssignedIdentities: {
|
|
149
|
+
'${aksIdentity.id}': {}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
properties: {
|
|
153
|
+
dnsPrefix: clusterName
|
|
154
|
+
kubernetesVersion: kubernetesVersion
|
|
155
|
+
agentPoolProfiles: [
|
|
156
|
+
{
|
|
157
|
+
name: 'default'
|
|
158
|
+
count: nodeCount
|
|
159
|
+
enableAutoScaling: false
|
|
160
|
+
vmSize: nodeVmSize
|
|
161
|
+
osDiskSizeGB: osDiskSizeGB
|
|
162
|
+
osDiskType: osDiskType
|
|
163
|
+
osType: 'Linux'
|
|
164
|
+
type: 'VirtualMachineScaleSets'
|
|
165
|
+
mode: 'System'
|
|
166
|
+
vnetSubnetID: subnet.id
|
|
167
|
+
nodeLabels: {
|
|
168
|
+
environment: 'rulebricks'
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
]
|
|
172
|
+
networkProfile: {
|
|
173
|
+
networkPlugin: 'azure'
|
|
174
|
+
networkPolicy: 'calico'
|
|
175
|
+
loadBalancerSku: 'standard'
|
|
176
|
+
serviceCidr: '10.0.0.0/16'
|
|
177
|
+
dnsServiceIP: '10.0.0.10'
|
|
178
|
+
}
|
|
179
|
+
oidcIssuerProfile: {
|
|
180
|
+
enabled: true
|
|
181
|
+
}
|
|
182
|
+
securityProfile: {
|
|
183
|
+
workloadIdentity: {
|
|
184
|
+
enabled: true
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
storageProfile: {
|
|
188
|
+
diskCSIDriver: {
|
|
189
|
+
enabled: true
|
|
190
|
+
}
|
|
191
|
+
fileCSIDriver: {
|
|
192
|
+
enabled: true
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
dependsOn: [
|
|
197
|
+
aksNetworkRole
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
resource externalDnsIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = if (enableExternalDns) {
|
|
202
|
+
name: '${clusterName}-external-dns'
|
|
203
|
+
location: location
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
resource externalDnsRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (enableExternalDns && (empty(dnsZoneResourceGroup) || dnsZoneResourceGroup == resourceGroup().name)) {
|
|
207
|
+
name: guid(resourceGroup().id, externalDnsIdentity!.id, 'DNS Zone Contributor')
|
|
208
|
+
scope: resourceGroup()
|
|
209
|
+
properties: {
|
|
210
|
+
roleDefinitionId: dnsZoneContributorRoleId
|
|
211
|
+
principalId: externalDnsIdentity!.properties.principalId
|
|
212
|
+
principalType: 'ServicePrincipal'
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
resource externalDnsFederatedCredential 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2023-01-31' = if (enableExternalDns) {
|
|
217
|
+
parent: externalDnsIdentity
|
|
218
|
+
name: 'external-dns'
|
|
219
|
+
properties: {
|
|
220
|
+
issuer: aks.properties.oidcIssuerProfile.issuerURL
|
|
221
|
+
subject: 'system:serviceaccount:${rulebricksNamespace}:external-dns'
|
|
222
|
+
audiences: [
|
|
223
|
+
'api://AzureADTokenExchange'
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
resource vectorIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = if (enableBlobLogging) {
|
|
229
|
+
name: '${clusterName}-vector'
|
|
230
|
+
location: location
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
resource loggingStorageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = if (enableBlobLogging && !empty(loggingStorageAccountName)) {
|
|
234
|
+
name: loggingStorageAccountName
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
resource vectorBlobRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (enableBlobLogging && !empty(loggingStorageAccountName)) {
|
|
238
|
+
name: guid(loggingStorageAccount.id, vectorIdentity!.id, 'Storage Blob Data Contributor')
|
|
239
|
+
scope: loggingStorageAccount
|
|
240
|
+
properties: {
|
|
241
|
+
roleDefinitionId: storageBlobDataContributorRoleId
|
|
242
|
+
principalId: vectorIdentity!.properties.principalId
|
|
243
|
+
principalType: 'ServicePrincipal'
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
resource vectorFederatedCredential 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2023-01-31' = if (enableBlobLogging) {
|
|
248
|
+
parent: vectorIdentity
|
|
249
|
+
name: 'vector'
|
|
250
|
+
properties: {
|
|
251
|
+
issuer: aks.properties.oidcIssuerProfile.issuerURL
|
|
252
|
+
subject: 'system:serviceaccount:${rulebricksNamespace}:${vectorServiceAccountName}'
|
|
253
|
+
audiences: [
|
|
254
|
+
'api://AzureADTokenExchange'
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
resource prometheusIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
|
|
260
|
+
name: '${clusterName}-prometheus'
|
|
261
|
+
location: location
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
resource prometheusFederatedCredential 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2023-01-31' = {
|
|
265
|
+
parent: prometheusIdentity
|
|
266
|
+
name: 'prometheus'
|
|
267
|
+
properties: {
|
|
268
|
+
issuer: aks.properties.oidcIssuerProfile.issuerURL
|
|
269
|
+
subject: 'system:serviceaccount:${rulebricksNamespace}:${prometheusServiceAccountName}'
|
|
270
|
+
audiences: [
|
|
271
|
+
'api://AzureADTokenExchange'
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
output clusterName string = aks.name
|
|
277
|
+
output resourceGroupName string = resourceGroup().name
|
|
278
|
+
output location string = location
|
|
279
|
+
output kubeconfigCommand string = 'az aks get-credentials --name ${clusterName} --resource-group ${resourceGroup().name}'
|
|
280
|
+
output externalDnsClientId string = enableExternalDns ? externalDnsIdentity!.properties.clientId : ''
|
|
281
|
+
output vectorClientId string = enableBlobLogging ? vectorIdentity!.properties.clientId : ''
|
|
282
|
+
output prometheusClientId string = prometheusIdentity.properties.clientId
|