├── .npmignore ├── images ├── console_error.png ├── bastion_connect.png ├── bastion_ssm_connect.png └── container_insights_1.png ├── .gitignore ├── test ├── manifests │ ├── network_policy_example.yaml │ ├── cluster_autoscaling_example.yaml │ ├── ebs_pod_example.yaml │ ├── efs_storageclass_example.yaml │ ├── hpa_example.yaml │ ├── secrets_providerdeployment_example.yaml │ └── alb_example.yaml └── test-deployment.sh ├── CODE_OF_CONDUCT.md ├── cdk.json ├── tsconfig.json ├── LICENSE ├── package.json ├── manifests ├── consoleViewOnlyGroup.yaml ├── awsSecretsManifest.yaml ├── metricServerManifest.yaml ├── otelContainerInsights.yaml └── fluentBitSetup.yaml ├── bin └── eks-cdk-js.ts ├── lib ├── vpc-stack.ts ├── k8s-nodegroup.ts ├── custom-resources │ └── eksloggingOnEvent.py ├── eks-cdk-js-stack.ts ├── policies │ └── policies.ts └── k8s-baseline.ts ├── .eslintrc.js ├── CONTRIBUTING.md ├── THIRD-PARTY-LICENSES └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /images/console_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-eks-using-cdk-typescript/HEAD/images/console_error.png -------------------------------------------------------------------------------- /images/bastion_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-eks-using-cdk-typescript/HEAD/images/bastion_connect.png -------------------------------------------------------------------------------- /images/bastion_ssm_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-eks-using-cdk-typescript/HEAD/images/bastion_ssm_connect.png -------------------------------------------------------------------------------- /images/container_insights_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-eks-using-cdk-typescript/HEAD/images/container_insights_1.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | !jest.config.js 3 | *.d.ts 4 | node_modules 5 | .vscode 6 | # CDK asset staging directory 7 | .cdk.staging 8 | cdk.out 9 | # Other files 10 | test/eks-cdk-js.test.ts 11 | cdk.context.json 12 | -------------------------------------------------------------------------------- /test/manifests/network_policy_example.yaml: -------------------------------------------------------------------------------- 1 | kind: NetworkPolicy 2 | apiVersion: networking.k8s.io/v1 3 | metadata: 4 | name: default-deny 5 | namespace: policy-test 6 | spec: 7 | podSelector: 8 | matchLabels: {} -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node --prefer-ts-exts bin/eks-cdk-js.ts", 3 | "context": { 4 | "eks-addon-vpc-cni-version": "v1.7.5-eksbuild.2", 5 | "eks-addon-kube-proxy-version": "v1.21.2-eksbuild.2", 6 | "eks-addon-coredns-version": "v1.8.4-eksbuild.1", 7 | "cluster-autoscaler-helm-version": "9.10.3", 8 | "aws-load-balancer-controller-helm-version": "1.2.3", 9 | "aws-ebs-csi-driver-helm-version": "2.0.4", 10 | "aws-efs-csi-driver-helm-version": "2.1.4", 11 | "secrets-store-csi-helm-version": "0.1.0", 12 | "aws-calico-helm-version": "0.3.5", 13 | "cluster_name" : "myfirstcluster" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/manifests/cluster_autoscaling_example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: cluster-autoscaler-test 5 | --- 6 | apiVersion: apps/v1 7 | kind: Deployment 8 | metadata: 9 | namespace: cluster-autoscaler-test 10 | name: httpd-deploy 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: httpd-deploy 16 | template: 17 | metadata: 18 | labels: 19 | app: httpd-deploy 20 | spec: 21 | containers: 22 | - image: httpd:2.4 23 | name: httpd-pod 24 | resources: 25 | requests: 26 | cpu: 500m 27 | memory: 256Mi -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2018"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization": false, 20 | "typeRoots": ["./node_modules/@types"] 21 | }, 22 | "exclude": ["cdk.out", "./node_modules/", "./test/"], 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eks-cdk-js", 3 | "version": "0.2.0", 4 | "bin": { 5 | "eks-cdk-js": "bin/eks-cdk-js.js" 6 | }, 7 | "scripts": { 8 | "build": "npm run lint && tsc", 9 | "watch": "tsc -w", 10 | "cdk": "npm run lint && cdk", 11 | "lint": "eslint -c .eslintrc.js ./bin/*.ts ./lib/*.ts --fix" 12 | }, 13 | "devDependencies": { 14 | "@typescript-eslint/eslint-plugin": "^4.28.4", 15 | "@typescript-eslint/parser": "^4.28.4", 16 | "eslint": "^7.31.0", 17 | "eslint-config-standard": "^16.0.3", 18 | "eslint-plugin-import": "^2.23.4", 19 | "eslint-plugin-node": "^11.1.0", 20 | "eslint-plugin-prettier": "^4.0.0", 21 | "eslint-plugin-promise": "^5.1.0", 22 | "ts-node": "^9.0.0" 23 | }, 24 | "dependencies": { 25 | "@types/js-yaml": "^4.0.1", 26 | "@types/node": "10.17.27", 27 | "aws-cdk-lib": "^2.0.0", 28 | "constructs": "^10.0.0", 29 | "js-yaml": "^4.1.0", 30 | "prettier": "^2.5.1", 31 | "typescript": "~3.9.7" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/manifests/ebs_pod_example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: ebs-csi-test 5 | --- 6 | kind: StorageClass 7 | apiVersion: storage.k8s.io/v1 8 | metadata: 9 | name: ebs-storage-class 10 | provisioner: ebs.csi.aws.com 11 | volumeBindingMode: WaitForFirstConsumer 12 | --- 13 | apiVersion: v1 14 | kind: PersistentVolumeClaim 15 | metadata: 16 | name: ebs-pvc 17 | namespace: ebs-csi-test 18 | spec: 19 | accessModes: 20 | - ReadWriteOnce 21 | storageClassName: ebs-storage-class 22 | resources: 23 | requests: 24 | storage: 8Gi 25 | --- 26 | apiVersion: v1 27 | kind: Pod 28 | metadata: 29 | namespace: ebs-csi-test 30 | name: ebs-app 31 | spec: 32 | containers: 33 | - name: ebs-app 34 | image: httpd:2.4 35 | command: ["/bin/sh"] 36 | args: ["-c", "while true; do echo $(date) >> /mount/log.txt; sleep 10; done"] 37 | volumeMounts: 38 | - name: ebs-volume 39 | mountPath: /mount/ 40 | volumes: 41 | - name: ebs-volume 42 | persistentVolumeClaim: 43 | claimName: ebs-pvc 44 | -------------------------------------------------------------------------------- /test/manifests/efs_storageclass_example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: efs-csi-test 5 | --- 6 | kind: StorageClass 7 | apiVersion: storage.k8s.io/v1 8 | metadata: 9 | name: efs-storage-class 10 | provisioner: efs.csi.aws.com 11 | parameters: 12 | provisioningMode: efs-ap 13 | fileSystemId: fs-123456 14 | directoryPerms: "700" 15 | --- 16 | apiVersion: v1 17 | kind: PersistentVolumeClaim 18 | metadata: 19 | name: efs-pvc 20 | namespace: efs-csi-test 21 | spec: 22 | accessModes: 23 | - ReadWriteMany 24 | storageClassName: efs-storage-class 25 | resources: 26 | requests: 27 | storage: 8Gi 28 | --- 29 | apiVersion: v1 30 | kind: Pod 31 | metadata: 32 | name: efs-app 33 | namespace: efs-csi-test 34 | spec: 35 | containers: 36 | - name: app 37 | image: httpd:2.4 38 | command: ["/bin/sh"] 39 | args: ["-c", "while true; do echo $(date) >> /mount/log.txt; sleep 10; done"] 40 | volumeMounts: 41 | - name: efs-storage 42 | mountPath: /mount 43 | volumes: 44 | - name: efs-storage 45 | persistentVolumeClaim: 46 | claimName: efs-pvc -------------------------------------------------------------------------------- /manifests/consoleViewOnlyGroup.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # From https://github.com/awsdocs/amazon-eks-user-guide/blob/master/doc_source/add-user-role.md 3 | # SPDX-License-Identifier: MIT-0 4 | 5 | apiVersion: rbac.authorization.k8s.io/v1 6 | kind: ClusterRole 7 | metadata: 8 | name: eks-console-dashboard-full-access-clusterrole 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - nodes 14 | - namespaces 15 | - pods 16 | verbs: 17 | - get 18 | - list 19 | - apiGroups: 20 | - apps 21 | resources: 22 | - deployments 23 | - daemonsets 24 | - statefulsets 25 | - replicasets 26 | verbs: 27 | - get 28 | - list 29 | - apiGroups: 30 | - batch 31 | resources: 32 | - jobs 33 | verbs: 34 | - get 35 | - list 36 | --- 37 | apiVersion: rbac.authorization.k8s.io/v1 38 | kind: ClusterRoleBinding 39 | metadata: 40 | name: eks-console-dashboard-full-access-binding 41 | subjects: 42 | - kind: Group 43 | name: eks-console-dashboard-full-access-group 44 | apiGroup: rbac.authorization.k8s.io 45 | roleRef: 46 | kind: ClusterRole 47 | name: eks-console-dashboard-full-access-clusterrole 48 | apiGroup: rbac.authorization.k8s.io 49 | -------------------------------------------------------------------------------- /test/manifests/hpa_example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: hpa-test 5 | --- 6 | apiVersion: v1 7 | kind: Service 8 | metadata: 9 | name: hpa-service 10 | namespace: hpa-test 11 | spec: 12 | selector: 13 | app.kubernetes.io/name : hpa-app 14 | ports: 15 | - port: 80 16 | --- 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | namespace: hpa-test 21 | name: hpa-deployment 22 | spec: 23 | selector: 24 | matchLabels: 25 | app.kubernetes.io/name: hpa-app 26 | replicas: 1 27 | template: 28 | metadata: 29 | labels: 30 | app.kubernetes.io/name: hpa-app 31 | spec: 32 | containers: 33 | - image: httpd:2.4 34 | imagePullPolicy: Always 35 | name: app-httpd 36 | ports: 37 | - containerPort: 80 38 | resources: 39 | limits: 40 | cpu: 500m 41 | requests: 42 | cpu: 100m 43 | --- 44 | apiVersion: autoscaling/v1 45 | kind: HorizontalPodAutoscaler 46 | metadata: 47 | name: hpa-deployment 48 | namespace: hpa-test 49 | spec: 50 | maxReplicas: 10 51 | minReplicas: 1 52 | scaleTargetRef: 53 | apiVersion: apps/v1 54 | kind: Deployment 55 | name: hpa-deployment 56 | targetCPUUtilizationPercentage: 50 57 | -------------------------------------------------------------------------------- /test/manifests/secrets_providerdeployment_example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: aws-secrets-manager-test 5 | --- 6 | apiVersion: secrets-store.csi.x-k8s.io/v1alpha1 7 | kind: SecretProviderClass 8 | metadata: 9 | name: httpd-deployment-aws-secrets-store 10 | namespace: aws-secrets-manager-test 11 | spec: 12 | provider: aws 13 | parameters: 14 | objects: | 15 | - objectName: "httpd-secrets-store" 16 | objectType: "secretsmanager" 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: httpd-deployment 22 | namespace: aws-secrets-manager-test 23 | labels: 24 | app: httpd 25 | spec: 26 | replicas: 2 27 | selector: 28 | matchLabels: 29 | app: httpd 30 | template: 31 | metadata: 32 | labels: 33 | app: httpd 34 | spec: 35 | serviceAccountName: httpd-deployment-sa 36 | volumes: 37 | - name: secrets-store 38 | csi: 39 | driver: secrets-store.csi.k8s.io 40 | readOnly: true 41 | volumeAttributes: 42 | secretProviderClass: "httpd-deployment-aws-secrets-store" 43 | containers: 44 | - name: httpd-deployment 45 | image: httpd 46 | ports: 47 | - containerPort: 80 48 | volumeMounts: 49 | - name: secrets-store 50 | mountPath: "/mount/secrets-store" 51 | readOnly: true 52 | 53 | -------------------------------------------------------------------------------- /bin/eks-cdk-js.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { App } from 'aws-cdk-lib'; 3 | import { Construct } from 'constructs'; 4 | import { Ekstack } from '../lib/eks-cdk-js-stack'; 5 | 6 | import { K8sBaselineStack } from '../lib/k8s-baseline'; 7 | import { K8snodegroups } from '../lib/k8s-nodegroup'; 8 | 9 | const DEFAULT_CONFIG = { 10 | env: { 11 | account: process.env.CDK_DEFAULT_ACCOUNT, 12 | region: process.env.CDK_DEFAULT_REGION, 13 | }, 14 | }; 15 | 16 | const app = new App(); 17 | const prefix = stackPrefix(app); 18 | const eks = new Ekstack(app, 'EKSStack', ({ 19 | env: DEFAULT_CONFIG.env, 20 | stackName: `${prefix}EKSStack`, 21 | })); 22 | 23 | const nodegroups = new K8snodegroups(app, 'EKSNodeGroups', ({ 24 | env: DEFAULT_CONFIG.env, 25 | stackName: `${prefix}EKSNodeGroups`, 26 | eksCluster: eks.cluster, 27 | nodeGroupRole: eks.createNodegroupRole('nodeGroup1'), 28 | })); 29 | 30 | const k8sbase = new K8sBaselineStack(app, 'EKSK8sBaseline', ({ 31 | env: DEFAULT_CONFIG.env, 32 | stackName: `${prefix}EKSK8sBaseline`, 33 | eksCluster: eks.cluster, 34 | 35 | })); 36 | 37 | k8sbase.addDependency(nodegroups); 38 | nodegroups.addDependency(eks); 39 | 40 | function stackPrefix (stack: Construct): string { 41 | const prefixValue = stack.node.tryGetContext('stack_prefix'); 42 | 43 | if (prefixValue !== undefined) { 44 | return prefixValue.trim(); 45 | } 46 | // if no stack_prefix return empty string 47 | return ''; 48 | } 49 | app.synth(); 50 | -------------------------------------------------------------------------------- /test/manifests/alb_example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: alb-ingress-test 5 | --- 6 | apiVersion: v1 7 | kind: Service 8 | metadata: 9 | namespace: alb-ingress-test 10 | name: alb-ingress-service 11 | spec: 12 | ports: 13 | - port: 80 14 | targetPort: 80 15 | protocol: TCP 16 | type: NodePort 17 | selector: 18 | app.kubernetes.io/name: alb-ingress-app 19 | --- 20 | apiVersion: apps/v1 21 | kind: Deployment 22 | metadata: 23 | namespace: alb-ingress-test 24 | name: alb-ingress-deployment 25 | spec: 26 | selector: 27 | matchLabels: 28 | app.kubernetes.io/name: alb-ingress-app 29 | replicas: 3 30 | template: 31 | metadata: 32 | labels: 33 | app.kubernetes.io/name: alb-ingress-app 34 | spec: 35 | containers: 36 | - image: httpd:2.4 37 | imagePullPolicy: Always 38 | name: app-httpd 39 | ports: 40 | - containerPort: 80 41 | --- 42 | apiVersion: networking.k8s.io/v1 43 | kind: Ingress 44 | metadata: 45 | namespace: alb-ingress-test 46 | name: ingress-httpd 47 | annotations: 48 | kubernetes.io/ingress.class: alb 49 | alb.ingress.kubernetes.io/scheme: internet-facing 50 | alb.ingress.kubernetes.io/target-type: ip 51 | alb.ingress.kubernetes.io/load-balancer-name: alb-ingress-httpd 52 | alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15' 53 | alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '10' 54 | spec: 55 | rules: 56 | - http: 57 | paths: 58 | - path: / 59 | pathType: Prefix 60 | backend: 61 | service: 62 | name: alb-ingress-service 63 | port: 64 | number: 80 65 | -------------------------------------------------------------------------------- /lib/vpc-stack.ts: -------------------------------------------------------------------------------- 1 | import { Stack } from 'aws-cdk-lib'; 2 | import { 3 | GatewayVpcEndpointAwsService, 4 | Vpc, 5 | FlowLogTrafficType, 6 | FlowLogDestination, 7 | InterfaceVpcEndpoint, 8 | } from 'aws-cdk-lib/aws-ec2'; 9 | 10 | // Private Endpoints 11 | // https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html#vpc-endpoints-private-clusters 12 | // EKS VPC Endpoint RoadMap https://github.com/aws/containers-roadmap/issues/298 13 | 14 | export function addEndpoint (stack: Stack, vpc: Vpc): void { 15 | // Additional VPC Endpoint for EKS https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html#vpc-endpoints-private-clusters 16 | (() => new InterfaceVpcEndpoint(stack, 'ecrapiVpcEndpoint', { 17 | open: true, 18 | vpc: vpc, 19 | service: { 20 | name: `com.amazonaws.${stack.region}.ecr.api`, 21 | port: 443, 22 | }, 23 | privateDnsEnabled: true, 24 | }))(); 25 | 26 | (() => new InterfaceVpcEndpoint(stack, 'ecradkrVpcEndpoint', { 27 | open: true, 28 | vpc: vpc, 29 | service: { 30 | name: `com.amazonaws.${stack.region}.ecr.dkr`, 31 | port: 443, 32 | }, 33 | privateDnsEnabled: true, 34 | }))(); 35 | } 36 | 37 | export const eksVpc = { 38 | cidr: '10.0.0.0/16', 39 | maxAzs: 3, 40 | // S3/DynamoDB https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-gateway.html 41 | gatewayEndpoints: { 42 | // S3 Gateway https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html#types-of-vpc-endpoints-for-s3 43 | // S3 Gateway vs Private Endpoint https://docs.aws.amazon.com/AmazonS3/latest/userguide/privatelink-interface-endpoints.html#types-of-vpc-endpoints-for-s3 44 | S3: { 45 | service: GatewayVpcEndpointAwsService.S3, 46 | }, 47 | 48 | }, 49 | flowLogs: { 50 | VpcFlowlogs: { 51 | destination: FlowLogDestination.toCloudWatchLogs(), 52 | trafficType: FlowLogTrafficType.ALL, 53 | }, 54 | }, 55 | // TWO Nat Gateways for higher availability 56 | natGateways: 2, 57 | }; 58 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | }, 5 | extends: ["standard", "plugin:import/typescript", "prettier"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | ecmaVersion: "2018", 9 | sourceType: "module", 10 | project: "./tsconfig.json", 11 | }, 12 | plugins: ["@typescript-eslint", "import", "prettier"], 13 | settings: { 14 | "import/parsers": { 15 | "@typescript-eslint/parser": [".ts", ".tsx"], 16 | }, 17 | "import/resolver": { 18 | node: {}, 19 | typescript: { 20 | directory: "./tsconfig.json", 21 | }, 22 | }, 23 | }, 24 | ignorePatterns: ["*cdk.out/*", "node_modules/", "*.js"], 25 | rules: { 26 | "@typescript-eslint/no-require-imports": ["error"], 27 | "@typescript-eslint/indent": ["error", 2], 28 | "comma-dangle": ["error", "always-multiline"], 29 | "comma-spacing": ["error", { before: false, after: true }], 30 | "array-bracket-newline": ["error", "consistent"], 31 | curly: ["error", "multi-line", "consistent"], 32 | "import/no-extraneous-dependencies": ["error"], 33 | "import/no-unresolved": ["error"], 34 | "import/order": [ 35 | "error", 36 | { 37 | groups: ["builtin", "external"], 38 | alphabetize: { order: "asc", caseInsensitive: true }, 39 | }, 40 | ], 41 | "no-duplicate-imports": ["error"], 42 | "@typescript-eslint/no-shadow": ["error"], 43 | semi: ["error", "always"], 44 | "quote-props": ["error", "consistent-as-needed"], 45 | "max-len": [ 46 | "error", 47 | { 48 | code: 150, 49 | ignoreUrls: true, 50 | ignoreStrings: true, 51 | ignoreTemplateLiterals: true, 52 | ignoreComments: true, 53 | ignoreRegExpLiterals: true, 54 | }, 55 | ], 56 | "@typescript-eslint/no-floating-promises": ["error"], 57 | "no-return-await": "off", 58 | "@typescript-eslint/return-await": "error", 59 | "no-console": ["error"], 60 | "no-bitwise": ["error"], 61 | }, 62 | }; 63 | -------------------------------------------------------------------------------- /manifests/awsSecretsManifest.yaml: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # From https://github.com/aws/secrets-store-csi-driver-provider-aws/blob/main/deployment/aws-provider-installer.yaml 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # https://kubernetes.io/docs/reference/access-authn-authz/rbac 6 | apiVersion: v1 7 | kind: ServiceAccount 8 | metadata: 9 | name: csi-secrets-store-provider-aws 10 | namespace: kube-system 11 | --- 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | kind: ClusterRole 14 | metadata: 15 | name: csi-secrets-store-provider-aws-cluster-role 16 | rules: 17 | - apiGroups: [""] 18 | resources: ["serviceaccounts/token"] 19 | verbs: ["create"] 20 | - apiGroups: [""] 21 | resources: ["serviceaccounts"] 22 | verbs: ["get"] 23 | - apiGroups: [""] 24 | resources: ["pods"] 25 | verbs: ["get"] 26 | - apiGroups: [""] 27 | resources: ["nodes"] 28 | verbs: ["get"] 29 | --- 30 | apiVersion: rbac.authorization.k8s.io/v1 31 | kind: ClusterRoleBinding 32 | metadata: 33 | name: csi-secrets-store-provider-aws-cluster-rolebinding 34 | roleRef: 35 | apiGroup: rbac.authorization.k8s.io 36 | kind: ClusterRole 37 | name: csi-secrets-store-provider-aws-cluster-role 38 | subjects: 39 | - kind: ServiceAccount 40 | name: csi-secrets-store-provider-aws 41 | namespace: kube-system 42 | --- 43 | apiVersion: apps/v1 44 | kind: DaemonSet 45 | metadata: 46 | namespace: kube-system 47 | name: csi-secrets-store-provider-aws 48 | labels: 49 | app: csi-secrets-store-provider-aws 50 | spec: 51 | updateStrategy: 52 | type: RollingUpdate 53 | selector: 54 | matchLabels: 55 | app: csi-secrets-store-provider-aws 56 | template: 57 | metadata: 58 | labels: 59 | app: csi-secrets-store-provider-aws 60 | spec: 61 | serviceAccountName: csi-secrets-store-provider-aws 62 | hostNetwork: true 63 | containers: 64 | - name: provider-aws-installer 65 | image: public.ecr.aws/aws-secrets-manager/secrets-store-csi-driver-provider-aws:1.0.r1-10-g1942553-2021.06.04.00.07-linux-amd64 66 | imagePullPolicy: Always 67 | args: 68 | - --provider-volume=/etc/kubernetes/secrets-store-csi-providers 69 | resources: 70 | requests: 71 | cpu: 50m 72 | memory: 100Mi 73 | limits: 74 | cpu: 50m 75 | memory: 100Mi 76 | volumeMounts: 77 | - mountPath: "/etc/kubernetes/secrets-store-csi-providers" 78 | name: providervol 79 | - name: mountpoint-dir 80 | mountPath: /var/lib/kubelet/pods 81 | mountPropagation: HostToContainer 82 | volumes: 83 | - name: providervol 84 | hostPath: 85 | path: "/etc/kubernetes/secrets-store-csi-providers" 86 | - name: mountpoint-dir 87 | hostPath: 88 | path: /var/lib/kubelet/pods 89 | type: DirectoryOrCreate 90 | nodeSelector: 91 | kubernetes.io/os: linux 92 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /manifests/metricServerManifest.yaml: -------------------------------------------------------------------------------- 1 | # From https://github.com/kubernetes-sigs/metrics-server/releases/tag/v0.5.0 2 | # SPDX-License-Identifier: Apache-2.0 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | labels: 7 | k8s-app: metrics-server 8 | name: metrics-server 9 | namespace: kube-system 10 | --- 11 | apiVersion: rbac.authorization.k8s.io/v1 12 | kind: ClusterRole 13 | metadata: 14 | labels: 15 | k8s-app: metrics-server 16 | rbac.authorization.k8s.io/aggregate-to-admin: "true" 17 | rbac.authorization.k8s.io/aggregate-to-edit: "true" 18 | rbac.authorization.k8s.io/aggregate-to-view: "true" 19 | name: system:aggregated-metrics-reader 20 | rules: 21 | - apiGroups: 22 | - metrics.k8s.io 23 | resources: 24 | - pods 25 | - nodes 26 | verbs: 27 | - get 28 | - list 29 | - watch 30 | --- 31 | apiVersion: rbac.authorization.k8s.io/v1 32 | kind: ClusterRole 33 | metadata: 34 | labels: 35 | k8s-app: metrics-server 36 | name: system:metrics-server 37 | rules: 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - pods 42 | - nodes 43 | - nodes/stats 44 | - namespaces 45 | - configmaps 46 | verbs: 47 | - get 48 | - list 49 | - watch 50 | --- 51 | apiVersion: rbac.authorization.k8s.io/v1 52 | kind: RoleBinding 53 | metadata: 54 | labels: 55 | k8s-app: metrics-server 56 | name: metrics-server-auth-reader 57 | namespace: kube-system 58 | roleRef: 59 | apiGroup: rbac.authorization.k8s.io 60 | kind: Role 61 | name: extension-apiserver-authentication-reader 62 | subjects: 63 | - kind: ServiceAccount 64 | name: metrics-server 65 | namespace: kube-system 66 | --- 67 | apiVersion: rbac.authorization.k8s.io/v1 68 | kind: ClusterRoleBinding 69 | metadata: 70 | labels: 71 | k8s-app: metrics-server 72 | name: metrics-server:system:auth-delegator 73 | roleRef: 74 | apiGroup: rbac.authorization.k8s.io 75 | kind: ClusterRole 76 | name: system:auth-delegator 77 | subjects: 78 | - kind: ServiceAccount 79 | name: metrics-server 80 | namespace: kube-system 81 | --- 82 | apiVersion: rbac.authorization.k8s.io/v1 83 | kind: ClusterRoleBinding 84 | metadata: 85 | labels: 86 | k8s-app: metrics-server 87 | name: system:metrics-server 88 | roleRef: 89 | apiGroup: rbac.authorization.k8s.io 90 | kind: ClusterRole 91 | name: system:metrics-server 92 | subjects: 93 | - kind: ServiceAccount 94 | name: metrics-server 95 | namespace: kube-system 96 | --- 97 | apiVersion: v1 98 | kind: Service 99 | metadata: 100 | labels: 101 | k8s-app: metrics-server 102 | name: metrics-server 103 | namespace: kube-system 104 | spec: 105 | ports: 106 | - name: https 107 | port: 443 108 | protocol: TCP 109 | targetPort: https 110 | selector: 111 | k8s-app: metrics-server 112 | --- 113 | apiVersion: apps/v1 114 | kind: Deployment 115 | metadata: 116 | labels: 117 | k8s-app: metrics-server 118 | name: metrics-server 119 | namespace: kube-system 120 | spec: 121 | selector: 122 | matchLabels: 123 | k8s-app: metrics-server 124 | strategy: 125 | rollingUpdate: 126 | maxUnavailable: 0 127 | template: 128 | metadata: 129 | labels: 130 | k8s-app: metrics-server 131 | spec: 132 | containers: 133 | - args: 134 | - --cert-dir=/tmp 135 | - --secure-port=443 136 | - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname 137 | - --kubelet-use-node-status-port 138 | - --metric-resolution=15s 139 | image: k8s.gcr.io/metrics-server/metrics-server:v0.5.0 140 | imagePullPolicy: IfNotPresent 141 | livenessProbe: 142 | failureThreshold: 3 143 | httpGet: 144 | path: /livez 145 | port: https 146 | scheme: HTTPS 147 | periodSeconds: 10 148 | name: metrics-server 149 | ports: 150 | - containerPort: 443 151 | name: https 152 | protocol: TCP 153 | readinessProbe: 154 | failureThreshold: 3 155 | httpGet: 156 | path: /readyz 157 | port: https 158 | scheme: HTTPS 159 | initialDelaySeconds: 20 160 | periodSeconds: 10 161 | resources: 162 | requests: 163 | cpu: 100m 164 | memory: 200Mi 165 | securityContext: 166 | readOnlyRootFilesystem: true 167 | runAsNonRoot: true 168 | runAsUser: 1000 169 | volumeMounts: 170 | - mountPath: /tmp 171 | name: tmp-dir 172 | nodeSelector: 173 | kubernetes.io/os: linux 174 | priorityClassName: system-cluster-critical 175 | serviceAccountName: metrics-server 176 | volumes: 177 | - emptyDir: {} 178 | name: tmp-dir 179 | --- 180 | apiVersion: apiregistration.k8s.io/v1 181 | kind: APIService 182 | metadata: 183 | labels: 184 | k8s-app: metrics-server 185 | name: v1beta1.metrics.k8s.io 186 | spec: 187 | group: metrics.k8s.io 188 | groupPriorityMinimum: 100 189 | insecureSkipTLSVerify: true 190 | service: 191 | name: metrics-server 192 | namespace: kube-system 193 | version: v1beta1 194 | versionPriority: 100 195 | -------------------------------------------------------------------------------- /lib/k8s-nodegroup.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import { CfnParameter, Fn } from 'aws-cdk-lib'; 3 | import { CfnLaunchTemplate, MultipartBody, MultipartUserData, UserData } from 'aws-cdk-lib/aws-ec2'; 4 | import { Cluster, Nodegroup } from 'aws-cdk-lib/aws-eks'; 5 | import { Role, ManagedPolicy } from 'aws-cdk-lib/aws-iam'; 6 | import { Construct } from 'constructs'; 7 | 8 | interface k8snodegroupsProps extends cdk.StackProps { 9 | eksCluster: Cluster, 10 | nodeGroupRole: Role 11 | } 12 | 13 | export class K8snodegroups extends cdk.Stack { 14 | constructor (scope: Construct, 15 | id: string, 16 | props: k8snodegroupsProps) { 17 | super(scope, id, props); 18 | const nodegroupMax = new CfnParameter(this, 'nodegroupMax', { 19 | type: 'Number', 20 | description: 'Max number of EKS worker nodes to scale up to', 21 | default: 10, 22 | }); 23 | const nodegroupCount = new CfnParameter(this, 'nodegroupCount', { 24 | type: 'Number', 25 | description: 'Desired Count of EKS Worker Nodes to launch', 26 | default: 2, 27 | }); 28 | const nodegroupMin = new CfnParameter(this, 'nodegroupMin', { 29 | type: 'Number', 30 | description: 'Min number of EKS worker nodes to scale down to', 31 | default: 2, 32 | }); 33 | const nodeType = new CfnParameter(this, 'nodegroupInstanceType', { 34 | type: 'String', 35 | description: 'Instance Type to be used with nodegroup ng-1', 36 | default: 't3.medium', 37 | }); 38 | const nodeAMIVersion = new CfnParameter(this, 'nodeAMIVersion', { 39 | type: 'String', 40 | default: '1.21.2-20210722', 41 | description: 'AMI version used for EKS Worker nodes https://docs.aws.amazon.com/eks/latest/userguide/eks-linux-ami-versions.html', 42 | }); 43 | 44 | const userdataCommands = UserData.forLinux(); 45 | // SSH only allowed via SSM Session Manager - https://aws.github.io/aws-eks-best-practices/security/docs/hosts/#minimize-access-to-worker-nodes 46 | userdataCommands.addCommands( 47 | `sudo yum install -y https://s3.${this.region}.amazonaws.com/amazon-ssm-${this.region}/latest/linux_amd64/amazon-ssm-agent.rpm`, 48 | ); 49 | const multipart = new MultipartUserData(); 50 | // const part = MultipartBody 51 | multipart.addPart( 52 | MultipartBody.fromUserData(userdataCommands), 53 | ); 54 | 55 | const launchtemplate = new CfnLaunchTemplate(this, 'LaunchTemplate', { 56 | launchTemplateData: { 57 | instanceType: nodeType.valueAsString, 58 | userData: Fn.base64(multipart.render()), 59 | // Ensure Managed Nodes Instances EBS Volumes are encrypted 60 | blockDeviceMappings: [ 61 | { 62 | deviceName: '/dev/xvda', 63 | ebs: { 64 | encrypted: true, 65 | volumeType: 'gp3', 66 | }, 67 | }, 68 | ], 69 | // Restrict access to the instance profile assigned to the worker node (not enabled) 70 | // Not all components are IMDSv2 aware. Ex. Fluentbit 71 | // https://aws.github.io/aws-eks-best-practices/security/docs/iam/#restrict-access-to-the-instance-profile-assigned-to-the-worker-node 72 | // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-metadataoptions.html#aws-properties-ec2-launchtemplate-launchtemplatedata-metadataoptions-properties 73 | // https://aws.github.io/aws-eks-best-practices/security/docs/iam/#when-your-application-needs-access-to-idms-use-imdsv2-and-increase-the-hop-limit-on-ec2-instances-to-2 74 | metadataOptions: { 75 | httpTokens: 'optional', 76 | httpPutResponseHopLimit: 2, 77 | 78 | }, 79 | tagSpecifications: [{ 80 | resourceType: 'instance', 81 | tags: [ 82 | { 83 | key: 'Name', 84 | value: Fn.join('-', [props.eksCluster.clusterName, 'WorkerNodes']), 85 | }, 86 | ], 87 | }], 88 | }, 89 | launchTemplateName: Fn.join('-', ['ng-1', props.eksCluster.clusterName]), 90 | 91 | }); 92 | props.nodeGroupRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore')); 93 | 94 | (() => new Nodegroup(this, 'ng-1', { 95 | cluster: props.eksCluster, 96 | // https://docs.aws.amazon.com/eks/latest/userguide/eks-linux-ami-versions.html 97 | releaseVersion: nodeAMIVersion.valueAsString, 98 | nodegroupName: 'ng-1', 99 | // Require specific order of max,desired,min or generated CDK Tokens fail desired>min check 100 | // https://github.com/aws/aws-cdk/issues/15485 101 | nodeRole: props.nodeGroupRole, 102 | maxSize: nodegroupMax.valueAsNumber, 103 | desiredSize: nodegroupCount.valueAsNumber, 104 | minSize: nodegroupMin.valueAsNumber, 105 | // LaunchTemplate for custom userdata to install SSM Agent 106 | launchTemplateSpec: { 107 | id: launchtemplate.ref, 108 | version: launchtemplate.attrLatestVersionNumber, 109 | }, 110 | tags: { 111 | Name: Fn.join('-', [props.eksCluster.clusterName, 'WorkerNodes']), 112 | }, 113 | }))(); 114 | // Permissions for SSM Manager for core functionality 115 | props.nodeGroupRole.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore')); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /lib/custom-resources/eksloggingOnEvent.py: -------------------------------------------------------------------------------- 1 | import time 2 | import boto3,botocore 3 | import json 4 | import logging 5 | 6 | import botocore 7 | boto3.set_stream_logger('botocore.waiter', logging.DEBUG) 8 | 9 | client = boto3.client('eks') 10 | 11 | ALL_LOGGING_OPTS = [ 'api','audit','authenticator','controllerManager','scheduler'] 12 | 13 | def on_event(event, context): 14 | print(json.dumps(event)) 15 | request_type = event['RequestType'] 16 | if request_type == 'Create': return on_create(event) 17 | if request_type == 'Update': return on_update(event) 18 | if request_type == 'Delete': return on_delete(event) 19 | raise Exception("Invalid request type: %s" % request_type) 20 | 21 | def on_create(event): 22 | props = event["ResourceProperties"] 23 | print("Update %s with logging configuration %s" % (props['eksCluster'], props['loggingOpts'])) 24 | try: 25 | currentLoggingOpts = { 26 | 'enabled': [], 27 | 'disabled': [] 28 | } 29 | eks_info = client.describe_cluster( 30 | name=props['eksCluster'] 31 | ) 32 | for item in eks_info['cluster']['logging']['clusterLogging']: 33 | if (item['enabled']== True): 34 | currentLoggingOpts['enabled'] = item 35 | elif (item['enabled'] == False): 36 | currentLoggingOpts['disabled'] = item 37 | else: 38 | print("Unable to parse current eks logging configuration %s" % eks_info['cluster']['logging']['clusterLogging']) 39 | raise ValueError() 40 | updateLogOpts=log_config_diff(currentLoggingOpts,props['loggingOpts']) 41 | print(updateLogOpts) 42 | eks=client.update_cluster_config( 43 | name= props['eksCluster'], 44 | logging={ 45 | 'clusterLogging': updateLogOpts 46 | }) 47 | print("%s" % eks) 48 | except client.exceptions.InvalidParameterException as i: 49 | if ('No changes needed for the logging config provided' == i.response['Error']['Message']): 50 | print('No changes needed for the logging config provided, current config is valid, skipping action returning success') 51 | pass 52 | except Exception as e: 53 | print(e) 54 | raise 55 | return {'Status': 'SUCCESS', 'PhysicalResourceId': props['eksCluster'], 'StackId': event['StackId'], 'LogicalResourceId': event['LogicalResourceId']} 56 | 57 | def on_update(event): 58 | physical_id = event["PhysicalResourceId"] 59 | props = event["ResourceProperties"] 60 | print("update resource %s with props %s" % (physical_id, props)) 61 | on_create(event) 62 | 63 | def on_delete(event): 64 | physical_id = event["PhysicalResourceId"] 65 | print("Skip delete since eks cluster will be deleted %s" % physical_id) 66 | return {'Status': 'SUCCESS', 'PhysicalResourceId': physical_id, 'StackId': event['StackId'], 'LogicalResourceId': event['LogicalResourceId']} 67 | 68 | 69 | 70 | def is_complete(event,context): 71 | print(event) 72 | props = event["ResourceProperties"] 73 | print("Starting Waiter") 74 | # Sleep for 30 seconds before checking for cluster status to change 75 | time.sleep(30) 76 | print("Waited 30 seconds") 77 | try: 78 | waiter = client.get_waiter('cluster_active') 79 | waiter.wait( 80 | name=props['eksCluster'], 81 | WaiterConfig={ 82 | 'Delay': 10, 83 | 'MaxAttempts' : 40 84 | } 85 | ) 86 | eks_info = client.describe_cluster( 87 | name=props['eksCluster'] 88 | ) 89 | print(eks_info['cluster']['logging']) 90 | print("Completed wait") 91 | except botocore.exceptions.WaiterError as e: 92 | print(e) 93 | if "Max attempts exceeded" in e.message: 94 | return {'IsComplete': False} 95 | except Exception as e: 96 | print(e) 97 | raise 98 | 99 | return { 'IsComplete': True } 100 | 101 | 102 | def log_config_diff(currentOpts,newOpts): 103 | print ("Evaluate for updated logging to be enabled") 104 | if "" in newOpts: 105 | newOpts.remove("") 106 | if 'types' not in currentOpts['enabled']: 107 | currentOpts['enabled'] = {'types': []} 108 | 109 | enabledOpts = set(newOpts) - set(currentOpts['enabled']['types']) 110 | print("Need \"%s\" logging to be enabled" % list(enabledOpts)) 111 | disabledOpts = set(ALL_LOGGING_OPTS) - set(newOpts) 112 | print ("Need \"%s\" logging to be disabled" % list(disabledOpts)) 113 | return [{ 114 | 'types': list(enabledOpts), 115 | 'enabled': True 116 | }, 117 | { 118 | 'types': list(disabledOpts), 119 | 'enabled': False 120 | }] 121 | 122 | if __name__ == "__main__": 123 | jsonObj = """{ 124 | "RequestType": "Create", 125 | "ServiceToken": "EXAMPLE", 126 | "ResponseURL": "EXAMPLE", 127 | "StackId": "arn:aws:cloudformation:us-west-2:ACCOUNT_ID:stack/EKS_STACK/EXAMPLE", 128 | "RequestId": "EXAMPLE", 129 | "LogicalResourceId": "eksLoggingCustomResource", 130 | "ResourceType": "AWS::CloudFormation::CustomResource", 131 | "ResourceProperties": { 132 | "ServiceToken": "test", 133 | "eksCluster": "myekscluster", 134 | "enable": "true", 135 | "loggingOpts": [ "" 136 | ] 137 | } 138 | }""" 139 | print(on_event(json.loads(jsonObj),'')) 140 | print(is_complete(json.loads(jsonObj),'')) -------------------------------------------------------------------------------- /manifests/otelContainerInsights.yaml: -------------------------------------------------------------------------------- 1 | # From https://github.com/aws-observability/aws-otel-collector/blob/main/deployment-template/eks/otel-container-insights-infra.yaml 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | # create namespace 5 | apiVersion: v1 6 | kind: Namespace 7 | metadata: 8 | name: aws-otel-eks 9 | labels: 10 | name: aws-otel-eks 11 | 12 | --- 13 | # create cwagent service account and role binding 14 | apiVersion: v1 15 | kind: ServiceAccount 16 | metadata: 17 | name: aws-otel-sa 18 | namespace: aws-otel-eks 19 | 20 | --- 21 | kind: ClusterRole 22 | apiVersion: rbac.authorization.k8s.io/v1 23 | metadata: 24 | name: aoc-agent-role 25 | rules: 26 | - apiGroups: [""] 27 | resources: ["pods", "nodes", "endpoints"] 28 | verbs: ["list", "watch"] 29 | - apiGroups: ["apps"] 30 | resources: ["replicasets"] 31 | verbs: ["list", "watch"] 32 | - apiGroups: ["batch"] 33 | resources: ["jobs"] 34 | verbs: ["list", "watch"] 35 | - apiGroups: [""] 36 | resources: ["nodes/proxy"] 37 | verbs: ["get"] 38 | - apiGroups: [""] 39 | resources: ["nodes/stats", "configmaps", "events"] 40 | verbs: ["create", "get"] 41 | - apiGroups: [""] 42 | resources: ["configmaps"] 43 | resourceNames: ["otel-container-insight-clusterleader"] 44 | verbs: ["get","update"] 45 | 46 | --- 47 | kind: ClusterRoleBinding 48 | apiVersion: rbac.authorization.k8s.io/v1 49 | metadata: 50 | name: aoc-agent-role-binding 51 | subjects: 52 | - kind: ServiceAccount 53 | name: aws-otel-sa 54 | namespace: aws-otel-eks 55 | roleRef: 56 | kind: ClusterRole 57 | name: aoc-agent-role 58 | apiGroup: rbac.authorization.k8s.io 59 | 60 | --- 61 | apiVersion: v1 62 | kind: ConfigMap 63 | metadata: 64 | name: otel-agent-conf 65 | namespace: aws-otel-eks 66 | labels: 67 | app: opentelemetry 68 | component: otel-agent-conf 69 | data: 70 | otel-agent-config: | 71 | extensions: 72 | health_check: 73 | 74 | receivers: 75 | awscontainerinsightreceiver: 76 | 77 | processors: 78 | batch/metrics: 79 | timeout: 60s 80 | 81 | exporters: 82 | awsemf: 83 | namespace: ContainerInsights 84 | log_group_name: '/aws/containerinsights/{ClusterName}/performance' 85 | log_stream_name: '{NodeName}' 86 | resource_to_telemetry_conversion: 87 | enabled: true 88 | dimension_rollup_option: NoDimensionRollup 89 | parse_json_encoded_attr_values: [Sources, kubernetes] 90 | metric_declarations: 91 | # node metrics 92 | - dimensions: [[NodeName, InstanceId, ClusterName]] 93 | metric_name_selectors: 94 | - node_cpu_utilization 95 | - node_memory_utilization 96 | - node_network_total_bytes 97 | - node_cpu_reserved_capacity 98 | - node_memory_reserved_capacity 99 | - node_number_of_running_pods 100 | - node_number_of_running_containers 101 | - dimensions: [[ClusterName]] 102 | metric_name_selectors: 103 | - node_cpu_utilization 104 | - node_memory_utilization 105 | - node_network_total_bytes 106 | - node_cpu_reserved_capacity 107 | - node_memory_reserved_capacity 108 | - node_number_of_running_pods 109 | - node_number_of_running_containers 110 | - node_cpu_usage_total 111 | - node_cpu_limit 112 | - node_memory_working_set 113 | - node_memory_limit 114 | 115 | # pod metrics 116 | - dimensions: [[PodName, Namespace, ClusterName], [Service, Namespace, ClusterName], [Namespace, ClusterName], [ClusterName]] 117 | metric_name_selectors: 118 | - pod_cpu_utilization 119 | - pod_memory_utilization 120 | - pod_network_rx_bytes 121 | - pod_network_tx_bytes 122 | - pod_cpu_utilization_over_pod_limit 123 | - pod_memory_utilization_over_pod_limit 124 | - dimensions: [[PodName, Namespace, ClusterName], [ClusterName]] 125 | metric_name_selectors: 126 | - pod_cpu_reserved_capacity 127 | - pod_memory_reserved_capacity 128 | - dimensions: [[PodName, Namespace, ClusterName]] 129 | metric_name_selectors: 130 | - pod_number_of_container_restarts 131 | 132 | # cluster metrics 133 | - dimensions: [[ClusterName]] 134 | metric_name_selectors: 135 | - cluster_node_count 136 | - cluster_failed_node_count 137 | 138 | # service metrics 139 | - dimensions: [[Service, Namespace, ClusterName], [ClusterName]] 140 | metric_name_selectors: 141 | - service_number_of_running_pods 142 | 143 | # node fs metrics 144 | - dimensions: [[NodeName, InstanceId, ClusterName], [ClusterName]] 145 | metric_name_selectors: 146 | - node_filesystem_utilization 147 | 148 | # namespace metrics 149 | - dimensions: [[Namespace, ClusterName], [ClusterName]] 150 | metric_name_selectors: 151 | - namespace_number_of_running_pods 152 | 153 | service: 154 | pipelines: 155 | metrics: 156 | receivers: [awscontainerinsightreceiver] 157 | processors: [batch/metrics] 158 | exporters: [awsemf] 159 | 160 | extensions: [health_check] 161 | 162 | 163 | --- 164 | # create Daemonset 165 | apiVersion: apps/v1 166 | kind: DaemonSet 167 | metadata: 168 | name: aws-otel-eks-ci 169 | namespace: aws-otel-eks 170 | spec: 171 | selector: 172 | matchLabels: 173 | name: aws-otel-eks-ci 174 | template: 175 | metadata: 176 | labels: 177 | name: aws-otel-eks-ci 178 | spec: 179 | containers: 180 | - name: aws-otel-collector 181 | image: amazon/aws-otel-collector:v0.11.0 182 | env: 183 | - name: K8S_NODE_NAME 184 | valueFrom: 185 | fieldRef: 186 | fieldPath: spec.nodeName 187 | - name: HOST_IP 188 | valueFrom: 189 | fieldRef: 190 | fieldPath: status.hostIP 191 | - name: HOST_NAME 192 | valueFrom: 193 | fieldRef: 194 | fieldPath: spec.nodeName 195 | - name: K8S_NAMESPACE 196 | valueFrom: 197 | fieldRef: 198 | fieldPath: metadata.namespace 199 | imagePullPolicy: Always 200 | command: 201 | - "/awscollector" 202 | - "--config=/conf/otel-agent-config.yaml" 203 | volumeMounts: 204 | - name: rootfs 205 | mountPath: /rootfs 206 | readOnly: true 207 | - name: dockersock 208 | mountPath: /var/run/docker.sock 209 | readOnly: true 210 | - name: varlibdocker 211 | mountPath: /var/lib/docker 212 | readOnly: true 213 | - name: sys 214 | mountPath: /sys 215 | readOnly: true 216 | - name: devdisk 217 | mountPath: /dev/disk 218 | readOnly: true 219 | - name: otel-agent-config-vol 220 | mountPath: /conf 221 | resources: 222 | limits: 223 | cpu: 200m 224 | memory: 200Mi 225 | requests: 226 | cpu: 200m 227 | memory: 200Mi 228 | volumes: 229 | - configMap: 230 | name: otel-agent-conf 231 | items: 232 | - key: otel-agent-config 233 | path: otel-agent-config.yaml 234 | name: otel-agent-config-vol 235 | - name: rootfs 236 | hostPath: 237 | path: / 238 | - name: dockersock 239 | hostPath: 240 | path: /var/run/docker.sock 241 | - name: varlibdocker 242 | hostPath: 243 | path: /var/lib/docker 244 | - name: sys 245 | hostPath: 246 | path: /sys 247 | - name: devdisk 248 | hostPath: 249 | path: /dev/disk/ 250 | serviceAccountName: aws-otel-sa -------------------------------------------------------------------------------- /THIRD-PARTY-LICENSES: -------------------------------------------------------------------------------- 1 | ** aws-secrets-store https://github.com/aws/secrets-store-csi-driver-provider-aws 2 | ** otel-collector https://github.com/aws-observability/aws-otel-collector/ 3 | ** metric-server https://github.com/kubernetes-sigs/metrics-server/ 4 | Apache License 5 | Version 2.0, January 2004 6 | http://www.apache.org/licenses/ 7 | 8 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 9 | 10 | 1. Definitions. 11 | 12 | "License" shall mean the terms and conditions for use, reproduction, 13 | and distribution as defined by Sections 1 through 9 of this document. 14 | 15 | "Licensor" shall mean the copyright owner or entity authorized by 16 | the copyright owner that is granting the License. 17 | 18 | "Legal Entity" shall mean the union of the acting entity and all 19 | other entities that control, are controlled by, or are under common 20 | control with that entity. For the purposes of this definition, 21 | "control" means (i) the power, direct or indirect, to cause the 22 | direction or management of such entity, whether by contract or 23 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 24 | outstanding shares, or (iii) beneficial ownership of such entity. 25 | 26 | "You" (or "Your") shall mean an individual or Legal Entity 27 | exercising permissions granted by this License. 28 | 29 | "Source" form shall mean the preferred form for making modifications, 30 | including but not limited to software source code, documentation 31 | source, and configuration files. 32 | 33 | "Object" form shall mean any form resulting from mechanical 34 | transformation or translation of a Source form, including but 35 | not limited to compiled object code, generated documentation, 36 | and conversions to other media types. 37 | 38 | "Work" shall mean the work of authorship, whether in Source or 39 | Object form, made available under the License, as indicated by a 40 | copyright notice that is included in or attached to the work 41 | (an example is provided in the Appendix below). 42 | 43 | "Derivative Works" shall mean any work, whether in Source or Object 44 | form, that is based on (or derived from) the Work and for which the 45 | editorial revisions, annotations, elaborations, or other modifications 46 | represent, as a whole, an original work of authorship. For the purposes 47 | of this License, Derivative Works shall not include works that remain 48 | separable from, or merely link (or bind by name) to the interfaces of, 49 | the Work and Derivative Works thereof. 50 | 51 | "Contribution" shall mean any work of authorship, including 52 | the original version of the Work and any modifications or additions 53 | to that Work or Derivative Works thereof, that is intentionally 54 | submitted to Licensor for inclusion in the Work by the copyright owner 55 | or by an individual or Legal Entity authorized to submit on behalf of 56 | the copyright owner. For the purposes of this definition, "submitted" 57 | means any form of electronic, verbal, or written communication sent 58 | to the Licensor or its representatives, including but not limited to 59 | communication on electronic mailing lists, source code control systems, 60 | and issue tracking systems that are managed by, or on behalf of, the 61 | Licensor for the purpose of discussing and improving the Work, but 62 | excluding communication that is conspicuously marked or otherwise 63 | designated in writing by the copyright owner as "Not a Contribution." 64 | 65 | "Contributor" shall mean Licensor and any individual or Legal Entity 66 | on behalf of whom a Contribution has been received by Licensor and 67 | subsequently incorporated within the Work. 68 | 69 | 2. Grant of Copyright License. Subject to the terms and conditions of 70 | this License, each Contributor hereby grants to You a perpetual, 71 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 72 | copyright license to reproduce, prepare Derivative Works of, 73 | publicly display, publicly perform, sublicense, and distribute the 74 | Work and such Derivative Works in Source or Object form. 75 | 76 | 3. Grant of Patent License. Subject to the terms and conditions of 77 | this License, each Contributor hereby grants to You a perpetual, 78 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 79 | (except as stated in this section) patent license to make, have made, 80 | use, offer to sell, sell, import, and otherwise transfer the Work, 81 | where such license applies only to those patent claims licensable 82 | by such Contributor that are necessarily infringed by their 83 | Contribution(s) alone or by combination of their Contribution(s) 84 | with the Work to which such Contribution(s) was submitted. If You 85 | institute patent litigation against any entity (including a 86 | cross-claim or counterclaim in a lawsuit) alleging that the Work 87 | or a Contribution incorporated within the Work constitutes direct 88 | or contributory patent infringement, then any patent licenses 89 | granted to You under this License for that Work shall terminate 90 | as of the date such litigation is filed. 91 | 92 | 4. Redistribution. You may reproduce and distribute copies of the 93 | Work or Derivative Works thereof in any medium, with or without 94 | modifications, and in Source or Object form, provided that You 95 | meet the following conditions: 96 | 97 | (a) You must give any other recipients of the Work or 98 | Derivative Works a copy of this License; and 99 | 100 | (b) You must cause any modified files to carry prominent notices 101 | stating that You changed the files; and 102 | 103 | (c) You must retain, in the Source form of any Derivative Works 104 | that You distribute, all copyright, patent, trademark, and 105 | attribution notices from the Source form of the Work, 106 | excluding those notices that do not pertain to any part of 107 | the Derivative Works; and 108 | 109 | (d) If the Work includes a "NOTICE" text file as part of its 110 | distribution, then any Derivative Works that You distribute must 111 | include a readable copy of the attribution notices contained 112 | within such NOTICE file, excluding those notices that do not 113 | pertain to any part of the Derivative Works, in at least one 114 | of the following places: within a NOTICE text file distributed 115 | as part of the Derivative Works; within the Source form or 116 | documentation, if provided along with the Derivative Works; or, 117 | within a display generated by the Derivative Works, if and 118 | wherever such third-party notices normally appear. The contents 119 | of the NOTICE file are for informational purposes only and 120 | do not modify the License. You may add Your own attribution 121 | notices within Derivative Works that You distribute, alongside 122 | or as an addendum to the NOTICE text from the Work, provided 123 | that such additional attribution notices cannot be construed 124 | as modifying the License. 125 | 126 | You may add Your own copyright statement to Your modifications and 127 | may provide additional or different license terms and conditions 128 | for use, reproduction, or distribution of Your modifications, or 129 | for any such Derivative Works as a whole, provided Your use, 130 | reproduction, and distribution of the Work otherwise complies with 131 | the conditions stated in this License. 132 | 133 | 5. Submission of Contributions. Unless You explicitly state otherwise, 134 | any Contribution intentionally submitted for inclusion in the Work 135 | by You to the Licensor shall be under the terms and conditions of 136 | this License, without any additional terms or conditions. 137 | Notwithstanding the above, nothing herein shall supersede or modify 138 | the terms of any separate license agreement you may have executed 139 | with Licensor regarding such Contributions. 140 | 141 | 6. Trademarks. This License does not grant permission to use the trade 142 | names, trademarks, service marks, or product names of the Licensor, 143 | except as required for reasonable and customary use in describing the 144 | origin of the Work and reproducing the content of the NOTICE file. 145 | 146 | 7. Disclaimer of Warranty. Unless required by applicable law or 147 | agreed to in writing, Licensor provides the Work (and each 148 | Contributor provides its Contributions) on an "AS IS" BASIS, 149 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 150 | implied, including, without limitation, any warranties or conditions 151 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 152 | PARTICULAR PURPOSE. You are solely responsible for determining the 153 | appropriateness of using or redistributing the Work and assume any 154 | risks associated with Your exercise of permissions under this License. 155 | 156 | 8. Limitation of Liability. In no event and under no legal theory, 157 | whether in tort (including negligence), contract, or otherwise, 158 | unless required by applicable law (such as deliberate and grossly 159 | negligent acts) or agreed to in writing, shall any Contributor be 160 | liable to You for damages, including any direct, indirect, special, 161 | incidental, or consequential damages of any character arising as a 162 | result of this License or out of the use or inability to use the 163 | Work (including but not limited to damages for loss of goodwill, 164 | work stoppage, computer failure or malfunction, or any and all 165 | other commercial damages or losses), even if such Contributor 166 | has been advised of the possibility of such damages. 167 | 168 | 9. Accepting Warranty or Additional Liability. While redistributing 169 | the Work or Derivative Works thereof, You may choose to offer, 170 | and charge a fee for, acceptance of support, warranty, indemnity, 171 | or other liability obligations and/or rights consistent with this 172 | License. However, in accepting such obligations, You may act only 173 | on Your own behalf and on Your sole responsibility, not on behalf 174 | of any other Contributor, and only if You agree to indemnify, 175 | defend, and hold each Contributor harmless for any liability 176 | incurred by, or claims asserted against, such Contributor by reason 177 | of your accepting any such warranty or additional liability. 178 | 179 | ** eks-user-guide https://github.com/awsdocs/amazon-eks-user-guide 180 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 181 | ** amazon cloudwatch insights https://github.com/aws-samples/amazon-cloudwatch-container-insights 182 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 183 | 184 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 185 | software and associated documentation files (the "Software"), to deal in the Software 186 | without restriction, including without limitation the rights to use, copy, modify, 187 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 188 | permit persons to whom the Software is furnished to do so. 189 | 190 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 191 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 192 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 193 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 194 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 195 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 196 | -------------------------------------------------------------------------------- /manifests/fluentBitSetup.yaml: -------------------------------------------------------------------------------- 1 | # From https://github.com/aws-samples/amazon-cloudwatch-container-insights/blob/master/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/fluent-bit/fluent-bit.yaml 2 | # SPDX-License-Identifier: MIT-0 3 | 4 | apiVersion: v1 5 | kind: ServiceAccount 6 | metadata: 7 | name: fluent-bit 8 | namespace: amazon-cloudwatch 9 | --- 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | kind: ClusterRole 12 | metadata: 13 | name: fluent-bit-role 14 | rules: 15 | - nonResourceURLs: 16 | - /metrics 17 | verbs: 18 | - get 19 | - apiGroups: [""] 20 | resources: 21 | - namespaces 22 | - pods 23 | - pods/logs 24 | verbs: ["get", "list", "watch"] 25 | --- 26 | apiVersion: rbac.authorization.k8s.io/v1 27 | kind: ClusterRoleBinding 28 | metadata: 29 | name: fluent-bit-role-binding 30 | roleRef: 31 | apiGroup: rbac.authorization.k8s.io 32 | kind: ClusterRole 33 | name: fluent-bit-role 34 | subjects: 35 | - kind: ServiceAccount 36 | name: fluent-bit 37 | namespace: amazon-cloudwatch 38 | --- 39 | apiVersion: v1 40 | kind: ConfigMap 41 | metadata: 42 | name: fluent-bit-config 43 | namespace: amazon-cloudwatch 44 | labels: 45 | k8s-app: fluent-bit 46 | data: 47 | fluent-bit.conf: | 48 | [SERVICE] 49 | Flush 5 50 | Log_Level info 51 | Daemon off 52 | Parsers_File parsers.conf 53 | HTTP_Server ${HTTP_SERVER} 54 | HTTP_Listen 0.0.0.0 55 | HTTP_Port ${HTTP_PORT} 56 | storage.path /var/fluent-bit/state/flb-storage/ 57 | storage.sync normal 58 | storage.checksum off 59 | storage.backlog.mem_limit 5M 60 | 61 | @INCLUDE application-log.conf 62 | @INCLUDE dataplane-log.conf 63 | @INCLUDE host-log.conf 64 | 65 | application-log.conf: | 66 | [INPUT] 67 | Name tail 68 | Tag application.* 69 | Exclude_Path /var/log/containers/cloudwatch-agent*, /var/log/containers/fluent-bit*, /var/log/containers/aws-node*, /var/log/containers/kube-proxy* 70 | Path /var/log/containers/*.log 71 | Docker_Mode On 72 | Docker_Mode_Flush 5 73 | Docker_Mode_Parser container_firstline 74 | Parser docker 75 | DB /var/fluent-bit/state/flb_container.db 76 | Mem_Buf_Limit 50MB 77 | Skip_Long_Lines On 78 | Refresh_Interval 10 79 | Rotate_Wait 30 80 | storage.type filesystem 81 | Read_from_Head ${READ_FROM_HEAD} 82 | 83 | [INPUT] 84 | Name tail 85 | Tag application.* 86 | Path /var/log/containers/fluent-bit* 87 | Parser docker 88 | DB /var/fluent-bit/state/flb_log.db 89 | Mem_Buf_Limit 5MB 90 | Skip_Long_Lines On 91 | Refresh_Interval 10 92 | Read_from_Head ${READ_FROM_HEAD} 93 | 94 | [INPUT] 95 | Name tail 96 | Tag application.* 97 | Path /var/log/containers/cloudwatch-agent* 98 | Docker_Mode On 99 | Docker_Mode_Flush 5 100 | Docker_Mode_Parser cwagent_firstline 101 | Parser docker 102 | DB /var/fluent-bit/state/flb_cwagent.db 103 | Mem_Buf_Limit 5MB 104 | Skip_Long_Lines On 105 | Refresh_Interval 10 106 | Read_from_Head ${READ_FROM_HEAD} 107 | 108 | [FILTER] 109 | Name kubernetes 110 | Match application.* 111 | Kube_URL https://kubernetes.default.svc:443 112 | Kube_Tag_Prefix application.var.log.containers. 113 | Merge_Log On 114 | Merge_Log_Key log_processed 115 | K8S-Logging.Parser On 116 | K8S-Logging.Exclude Off 117 | Labels Off 118 | Annotations Off 119 | 120 | [OUTPUT] 121 | Name cloudwatch_logs 122 | Match application.* 123 | region ${AWS_REGION} 124 | log_group_name /aws/containerinsights/${CLUSTER_NAME}/application 125 | log_stream_prefix ${HOST_NAME}- 126 | auto_create_group true 127 | extra_user_agent container-insights 128 | 129 | dataplane-log.conf: | 130 | [INPUT] 131 | Name systemd 132 | Tag dataplane.systemd.* 133 | Systemd_Filter _SYSTEMD_UNIT=docker.service 134 | Systemd_Filter _SYSTEMD_UNIT=kubelet.service 135 | DB /var/fluent-bit/state/systemd.db 136 | Path /var/log/journal 137 | Read_From_Tail ${READ_FROM_TAIL} 138 | 139 | [INPUT] 140 | Name tail 141 | Tag dataplane.tail.* 142 | Path /var/log/containers/aws-node*, /var/log/containers/kube-proxy* 143 | Docker_Mode On 144 | Docker_Mode_Flush 5 145 | Docker_Mode_Parser container_firstline 146 | Parser docker 147 | DB /var/fluent-bit/state/flb_dataplane_tail.db 148 | Mem_Buf_Limit 50MB 149 | Skip_Long_Lines On 150 | Refresh_Interval 10 151 | Rotate_Wait 30 152 | storage.type filesystem 153 | Read_from_Head ${READ_FROM_HEAD} 154 | 155 | [FILTER] 156 | Name modify 157 | Match dataplane.systemd.* 158 | Rename _HOSTNAME hostname 159 | Rename _SYSTEMD_UNIT systemd_unit 160 | Rename MESSAGE message 161 | Remove_regex ^((?!hostname|systemd_unit|message).)*$ 162 | 163 | [FILTER] 164 | Name aws 165 | Match dataplane.* 166 | imds_version v1 167 | 168 | [OUTPUT] 169 | Name cloudwatch_logs 170 | Match dataplane.* 171 | region ${AWS_REGION} 172 | log_group_name /aws/containerinsights/${CLUSTER_NAME}/dataplane 173 | log_stream_prefix ${HOST_NAME}- 174 | auto_create_group true 175 | extra_user_agent container-insights 176 | 177 | host-log.conf: | 178 | [INPUT] 179 | Name tail 180 | Tag host.dmesg 181 | Path /var/log/dmesg 182 | Parser syslog 183 | DB /var/fluent-bit/state/flb_dmesg.db 184 | Mem_Buf_Limit 5MB 185 | Skip_Long_Lines On 186 | Refresh_Interval 10 187 | Read_from_Head ${READ_FROM_HEAD} 188 | 189 | [INPUT] 190 | Name tail 191 | Tag host.messages 192 | Path /var/log/messages 193 | Parser syslog 194 | DB /var/fluent-bit/state/flb_messages.db 195 | Mem_Buf_Limit 5MB 196 | Skip_Long_Lines On 197 | Refresh_Interval 10 198 | Read_from_Head ${READ_FROM_HEAD} 199 | 200 | [INPUT] 201 | Name tail 202 | Tag host.secure 203 | Path /var/log/secure 204 | Parser syslog 205 | DB /var/fluent-bit/state/flb_secure.db 206 | Mem_Buf_Limit 5MB 207 | Skip_Long_Lines On 208 | Refresh_Interval 10 209 | Read_from_Head ${READ_FROM_HEAD} 210 | 211 | [FILTER] 212 | Name aws 213 | Match host.* 214 | imds_version v1 215 | 216 | [OUTPUT] 217 | Name cloudwatch_logs 218 | Match host.* 219 | region ${AWS_REGION} 220 | log_group_name /aws/containerinsights/${CLUSTER_NAME}/host 221 | log_stream_prefix ${HOST_NAME}. 222 | auto_create_group true 223 | extra_user_agent container-insights 224 | 225 | parsers.conf: | 226 | [PARSER] 227 | Name docker 228 | Format json 229 | Time_Key time 230 | Time_Format %Y-%m-%dT%H:%M:%S.%LZ 231 | 232 | [PARSER] 233 | Name syslog 234 | Format regex 235 | Regex ^(?