Self Hosted Installation on AWS EKS
To install and run Mission Control you need to have the following prerequisites:
- EKS 1.28+ with an Ingress Controller
- 500m - 2000m of CPU and 6 - 8GB of Memory (2 - 4GB if using an external DB)
- Persistent Volumes with 20GB+ of storage or an external postgres database like RDS
- (Optional) SMTP Server (For sending notifications and invites)
Depending on how you want to use Mission Control you need to create an IAM role for mission control to use:
Use Case | Role |
---|---|
Read Only Scraping | arn:aws:iam::aws:policy/ReadOnlyAccess |
Playbooks to create and update AWS Resources | arn:aws:iam::aws:policy/PowerUserAccess |
Create new IAM Policy (Alternative)
You can also create a new policy with just the permissions required by Mission Control
iam-policy.json{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "mission-control-config-role",
"Effect": "Allow",
"Action": [
"acm:Describe*",
"acm:Get*",
"acm:List*",
"cloudtrail:LookupEvents",
"config:BatchGetAggregateResourceConfig",
"config:BatchGetResourceConfig",
"config:Describe*",
"config:Get*",
"config:List*",
"config:SelectAggregateResourceConfig",
"config:SelectResourceConfig",
"ec2:Describe*",
"ecr:Describe*",
"eks:Describe*",
"eks:ListClusters",
"elasticfilesystem:Describe*",
"elasticloadbalancing:Describe*",
"guardduty:Describe*",
"guardduty:Get*",
"guardduty:List*",
"iam:GetAccountName",
"iam:GetAccountSummary",
"iam:GetGroup",
"iam:GetGroupPolicy",
"iam:GetInstanceProfile",
"iam:GetLoginProfile",
"iam:GetPolicy",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:GetUser",
"iam:List*",
"lambda:List*",
"rds:Describe*",
"sts:GetCallerIdentity"
"trustedadvisor:Describe*",
"trustedadvisor:DownloadRisk",
"trustedadvisor:Get*",
"trustedadvisor:List*",
],
"Resource": "*"
}
]
}
- IAM Roles for Service Accounts
- Pod Identity
- Access Key
- eksctl
-
Setup variables
# The name of the EKS cluster mission control is being deployed to
export CLUSTER= <CLUSTER_NAME>
# the default namespace the mission-control helm chart uses
export NAMESPACE=mission-control
export ACCOUNT=$(aws sts get-caller-identity --query 'Account' --output text) -
Enable EKS IAM Roles for Service Accounts
eksctl utils associate-iam-oidc-provider --cluster=$CLUSTER
-
Create the IAM Role mappings
eksctl.yamliam:
withOIDC: true
serviceAccounts:
- metadata:
name: mission-control-sa
namespace: mission-control
roleName: MissionControlRole
roleOnly: true
attachPolicyARNs:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
- metadata:
name: canary-checker-sa
namespace: mission-control
roleName: CanaryCheckerRole
roleOnly: true
attachPolicyARNs:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
- metadata:
name: config-db-sa
namespace: mission-control
roleName: ConfigDBRole
roleOnly: true
attachPolicyARNs:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"eksctl create iamserviceaccount --cluster $CLUSTER -c eksctl.yaml
-
Choose a routable
DOMAIN
for Mission ControlSee Ingress for more options on configuring the ingress including generating certs with cert-manager
See Local Testing for testing using a kind or minikube without a routable domain
-
Install Mission Control
See values.yaml- Helm
- Flux
cat > values.yaml << EOF
serviceAccount:
annotations:
# used by mission control for notifications / playbooks
eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT:role/MissionControlRole
canary-checker:
serviceAccount:
annotations:
# used for cloudwatch, S3 and other AWS health checks
eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT:role/CanaryCheckerRole
config-db:
serviceAccount:
annotations:
# used to scrape AWS resources, change history via AWS CloudTrail and cost via Athena
eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT:role/ConfigDBRole
EOF
helm repo add flanksource https://flanksource.github.io/charts
helm repo update
helm install mission-control flanksource/mission-control \
--set global.ui.host=DOMAIN \
--set-file values.yaml \
-n mission-control --create-namespace \
--waitapiVersion: v1
kind: Namespace
metadata:
name: mission-control
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: flanksource
namespace: mission-control
spec:
interval: 5m0s
url: https://flanksource.github.io/charts
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: mission-control
namespace: mission-control
spec:
chart:
spec:
chart: mission-control
sourceRef:
kind: HelmRepository
name: flanksource
namespace: mission-control
interval: 1m
values:
serviceAccount:
annotations:
# used by mission control for notifications / playbooks
eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT:role/MissionControlRole
canary-checker:
serviceAccount:
annotations:
# used for cloudwatch, S3 and other AWS health checks
eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT:role/CanaryCheckerRole
config-db:
serviceAccount:
annotations:
# used to scrape AWS resources, change history via AWS CloudTrail and cost via Athena
eks.amazonaws.com/role-arn: arn:aws:iam::$ACCOUNT:role/ConfigDBRole
global.ui.host: DOMAIN
- eksctl
- Terraform
- Cloudformation
-
Ensure the AWS Pod Identity Agent is configured and running
-
Create a mapping file for
eksctl
eksctl.yamlpodIdentityAssociations:
- namespace: mission-control
serviceAccountName: mission-control-sa
permissionPolicyARNs: arn:aws:iam::aws:policy/ReadOnlyAccess
- namespace: mission-control
serviceAccountName: config-db-sa
permissionPolicyARNs: arn:aws:iam::aws:policy/ReadOnlyAccess
- namespace: mission-control
serviceAccountName: canary-checker-sa
permissionPolicyARNs: arn:aws:iam::aws:policy/ReadOnlyAccess
iam:
# note withOIDC is not required for Pod Identity
serviceAccounts:
# used by mission control for notifications / playbooks
- metadata:
name: mission-control-sa
namespace: mission-control
attachPolicyARNs:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
# used for cloudwatch, S3 and other AWS health checks
- metadata:
name: canary-checker-sa
namespace: mission-control
attachPolicyARNs:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
# used to scrape resources, AWS CloudTrail and AWS Cost & Usage Reports
- metadata:
name: config-db-sa
namespace: mission-control
attachPolicyARNs:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"Using an existing IAM Role
If you are using a pre-existing IAM role when creating a pod identity association, you must configure the role to trust the newly introduced EKS service principal (
pods.eks.amazonaws.com
)iam-trust-policy.json{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "pods.eks.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
} -
Apply the Pod Identities using
eksctl
eksctl create podidentityassociation -c eksctl.yaml
-
Choose a routable
DOMAIN
for Mission ControlSee Ingress for more options on configuring the ingress including generating certs with cert-manager
See Local Testing for testing using a kind or minikube without a routable domain
-
Install Mission Control
See values.yaml- Helm
- Flux
helm repo add flanksource https://flanksource.github.io/charts
helm repo update
helm install mission-control flanksource/mission-control \
--set global.ui.host=DOMAIN \
-n mission-control --create-namespace \
--waitapiVersion: v1
kind: Namespace
metadata:
name: mission-control
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: flanksource
namespace: mission-control
spec:
interval: 5m0s
url: https://flanksource.github.io/charts
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: mission-control
namespace: mission-control
spec:
chart:
spec:
chart: mission-control
sourceRef:
kind: HelmRepository
name: flanksource
namespace: mission-control
interval: 1m
values:
global.ui.host: DOMAIN
-
Ensure the AWS Pod Identity Agent is configured and running
-
Create
main.tf
main.tfvariable "cluster" {
type = string
}
variable "role" {
type = string
}
variable "namespace" {
type = string
default = "mission-control"
}
variable "policy" {
type = string
default = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}
locals {
service_accounts = [
"mission-control-sa",
"canary-checker-sa",
"config-db-sa"
]
}
data "aws_caller_identity" "current" {}
resource "aws_iam_role" "mission-control" {
name = "MissionControlRole"
assume_role_policy = jsonencode({
Statement = [{
Action = [
"sts:AssumeRole",
"sts:TagSession"
]
Effect = "Allow"
Principal = {
Service: "pods.eks.amazonaws.com"
}
}]
Version = "2012-10-17"
})
}
resource "aws_iam_role_policy_attachment" "mission-control" {
policy_arn = var.policy
role = aws_iam_role.mission-control.name
}
resource "aws_eks_pod_identity_association" "pod_identities" {
for_each = local.service_accounts
cluster_name = var.cluster
namespace = var.namespace
service_account = each.value
role_arn = var.role
} -
Apply the terraform
TF_VAR_role=$CLUSTER terraform apply
-
Install Mission Control
See values.yaml- Helm
- Flux
helm repo add flanksource https://flanksource.github.io/charts
helm repo update
helm install mission-control flanksource/mission-control \
--set global.ui.host=DOMAIN \
-n mission-control --create-namespace \
--waitapiVersion: v1
kind: Namespace
metadata:
name: mission-control
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: flanksource
namespace: mission-control
spec:
interval: 5m0s
url: https://flanksource.github.io/charts
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: mission-control
namespace: mission-control
spec:
chart:
spec:
chart: mission-control
sourceRef:
kind: HelmRepository
name: flanksource
namespace: mission-control
interval: 1m
values:
global.ui.host: DOMAIN
- Associate Pod Identities
mission-control-iam-cloudformation.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: CloudFormation template for Mission Control IAM Role using EKS Pod Identities
Parameters:
Cluster:
Type: String
Description: Name of the EKS cluster
Namespace:
Type: String
Default: "mission-control"
Description: Kubernetes namespace
PolicyArn:
Type: String
Default: "arn:aws:iam::aws:policy/ReadOnlyAccess"
Description: ARN of the IAM policy to attach to the role
Resources:
MissionControlRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "MissionControlRole"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "eks.amazonaws.com"
Action:
- "sts:AssumeRole"
- "sts:TagSession"
MissionControlRolePolicyAttachment:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: "MissionControlPolicy"
Roles:
- Ref: "MissionControlRole"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "*"
Resource: "*"
MissionControlServiceAccount:
Type: "AWS::EKS::PodIdentityAssociation"
Properties:
ClusterName: !Ref "Cluster"
Namespace: !Ref "Namespace"
RoleArn: !GetAtt MissionControlRole.Arn
ServiceAccount: mission-control-sa
CanaryCheckerServiceAccount:
Type: "AWS::EKS::PodIdentityAssociation"
Properties:
ClusterName: !Ref "Cluster"
Namespace: !Ref "Namespace"
RoleArn: !GetAtt MissionControlRole.Arn
ServiceAccount: canary-checker-sa
ConfigDBServiceAccount:
Type: "AWS::EKS::PodIdentityAssociation"
Properties:
ClusterName: !Ref "Cluster"
Namespace: !Ref "Namespace"
RoleArn: !GetAtt MissionControlRole.Arn
ServiceAccount: config-db-sa - Install Mission Control
See values.yaml
- Helm
- Flux
helm repo add flanksource https://flanksource.github.io/charts
helm repo update
helm install mission-control flanksource/mission-control \
-n mission-control --create-namespace \
--waitapiVersion: v1
kind: Namespace
metadata:
name: mission-control
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: flanksource
namespace: mission-control
spec:
interval: 5m0s
url: https://flanksource.github.io/charts
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: mission-control
namespace: mission-control
spec:
chart:
spec:
chart: mission-control
sourceRef:
kind: HelmRepository
name: flanksource
namespace: mission-control
interval: 1m
values:
Using Access Keys and Secrets is not recommended from a security perspective
First we create a secret called aws
containing the access key and secret, This secret is not s
-
Create a new IAM User and Access Key
USER_NAME="mission-control-sa"
aws iam create-user --user-name $USER_NAME
aws iam attach-user-policy --user-name $USER_NAME --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
key=$(aws iam create-access-key --user-name $USER_NAME) -
Create a new secret
aws
containing the access and secret keykubectl create secret generic aws \
--from-literal=AWS_ACCESS_KEY_ID=$(echo $key | jq -r '.AccessKey.AccessKeyId') \
--from-literal=AWS_SECRET_ACCESS_KEY=$(echo $key | jq -r '.AccessKey.SecretAccessKey') -
Create a new connection to use bundles
aws-connection.yamlapiVersion: mission-control.flanksource.com/v1
kind: Connection
metadata:
name: aws
spec:
region: eu-west-1
accessKey:
valueFrom:
secretKeyRef:
name: aws
key: AWS_ACCESS_KEY_ID
secretKey:
valueFrom:
secretKeyRef:
name: aws
key: AWS_ACCESS_KEY_ID
kubectl create secret generic aws \
--from-literal=AWS_ACCESS_KEY_ID=$(echo $key | jq -r '.AccessKey.AccessKeyId') \
--from-literal=AWS_SECRET_ACCESS_KEY=$(echo $key | jq -r '.AccessKey.SecretAccessKey')
Next Steps
Install the AWS registry chart to configure the AWS Scraper