diff --git a/README.md b/README.md index d759529..876a843 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ as well as a reference and starting place for your own deployments. ### Kubernetes * `Pro` [kubernetes](./kubernetes) +* `Pro` [Helm Chart](./kubernetes/helm/rundeckpro) ### Plugin Bundling * [cloud](./cloud) diff --git a/kubernetes/helm/rundeckpro/Chart.yaml b/kubernetes/helm/rundeckpro/Chart.yaml new file mode 100644 index 0000000..cdd8b18 --- /dev/null +++ b/kubernetes/helm/rundeckpro/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: rundeckpro +description: A Helm chart for deploying PagerDuty Runbook Automation (formerly Rundeck) on AWS EKS +type: application +version: 0.1.0 +appVersion: "5.17.0" +keywords: + - rundeck + - runbook-automation + - pagerduty + - automation + - eks +sources: + - https://github.com/rundeck/docker-zoo diff --git a/kubernetes/helm/rundeckpro/README.md b/kubernetes/helm/rundeckpro/README.md new file mode 100644 index 0000000..ef9969f --- /dev/null +++ b/kubernetes/helm/rundeckpro/README.md @@ -0,0 +1,458 @@ +# Runbook Automation Helm Chart for AWS EKS + +## Introduction + +This Helm chart deploys PagerDuty Runbook Automation (formerly Rundeck) on AWS EKS in a production-ready, highly available configuration. Helm is the package manager for Kubernetes, making it easier to define, install, and upgrade even the most complex Kubernetes applications. + +Using a Helm chart instead of raw manifest files offers several advantages: + +- **Reusability:** Helm charts can be parameterized, making them reusable across environments. +- **Versioning:** Charts can be versioned and rolled back easily. +- **Simplicity:** A single command can install or upgrade all resources, reducing manual steps. +- **Consistency:** Ensures all resources are deployed together, minimizing configuration drift. +- **Templating:** Values can be injected at deploy time, supporting different configurations for dev, staging, and prod. + +This guide uses AWS EKS as the Kubernetes engine and integrates with AWS services like Route53 for DNS, S3 for log storage, and RDS for the database. + +## Architecture Overview + +This chart deploys Runbook Automation in a clustered configuration with: + +- **High Availability:** Multiple replicas with session affinity +- **Load Balancing:** AWS Application Load Balancer (ALB) with SSL termination +- **Persistent Storage:** RDS for database and S3 for execution logs +- **DNS Management:** ExternalDNS for automatic Route53 updates +- **Security:** Kubernetes secrets for sensitive data + +## File Overview + +Here's a brief explanation of each file in this chart: + +### Chart Files + +- **Chart.yaml** + Contains metadata about the Helm chart, such as name, version, description, maintainers, and keywords. + +- **values.yaml** + The default configuration values for the chart. Users can override these when installing or upgrading the chart. Contains example values with placeholders for environment-specific settings. + +### Template Files + +- **templates/_helpers.tpl** + Template helpers file containing reusable template snippets (like naming conventions) to keep the chart DRY and maintainable. + +- **templates/deployment.yaml** + The Kubernetes Deployment template defining how Rundeck pods are created and managed. Includes environment variables, resource limits, volume mounts, and cluster configuration. + +- **templates/service.yaml** + The Kubernetes Service template exposing Rundeck within the cluster with session affinity for maintaining user sessions. + +- **templates/ingress.yaml** + The Kubernetes Ingress template managing external access via AWS ALB with SSL termination and health checks. + +- **templates/secrets.yaml** + The Kubernetes Secret templates for ACL files, kubeconfig, and realm properties. These are populated using `--set-file` during installation. + +- **templates/configMap.yaml** + ConfigMap templates for node sources and optional certificate configurations. + +## Prerequisites + +Before deploying this Helm chart, ensure you have: + +### Required Tools + +- **Helm 3.x** installed on your local machine or CI/CD environment +- **kubectl** configured to access your EKS cluster +- **AWS CLI** configured with appropriate permissions + +### Required AWS Infrastructure + +- **EKS Cluster** with appropriate node groups +- **AWS Load Balancer Controller** - [Installation Guide](https://docs.aws.amazon.com/eks/latest/userguide/lbc-helm.html) + - Enables management of AWS ALB directly from Kubernetes +- **ExternalDNS** - [Installation Guide](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws-load-balancer-controller.md) + - Automatically updates Route53 DNS records +- **RDS Database** (MySQL/MariaDB compatible with Rundeck) +- **S3 Bucket** for execution log storage +- **Route53 Hosted Zone** for DNS management +- **ACM Certificate** for your domain + +### IAM Permissions + +Your EKS nodes need IAM permissions for: +- Reading/writing to S3 bucket +- Connecting to RDS database +- (Optional) Reading secrets from AWS Secrets Manager + +## Required Secrets + +This chart expects several secrets to be configured before installation: + +### 1. ACL File Secret (Admin Permissions) + +The ACL (Access Control List) file defines administrative permissions for Rundeck. Create the required secret using Helm's `--set-file` option during installation: + +```bash +helm install rundeckpro . \ + --set-file aclFile=/path/to/admin-role.aclpolicy +``` + +**Example ACL file** (`admin-role.aclpolicy`): +```yaml +description: Admin project level access control +context: + project: '.*' # all projects +for: + resource: + - equals: + kind: job + allow: [create, delete, read, update, run, kill] + - equals: + kind: node + allow: [read, create, update, refresh] + - equals: + kind: event + allow: [read, create] + adhoc: + - allow: [read, run, kill] + node: + - allow: [read, run] +by: + group: admin +--- +description: Admin Application level access control +context: + application: 'rundeck' +for: + resource: + - equals: + kind: project + allow: [create, delete, read, update] + - equals: + kind: system + allow: [read, enable_executions, disable_executions, admin] + - equals: + kind: system_acl + allow: [read, create, update, delete, admin] + - equals: + kind: user + allow: [admin] + project: + - match: + name: '.*' + allow: [read, import, export, configure, delete, admin] + storage: + - match: + path: '(keys|keys/.*)' + allow: [read, create, update, delete] +by: + group: admin +``` + +### 2. Kubeconfig File Secret (Optional) + +If you want Rundeck to manage Kubernetes resources, provide a kubeconfig file: + +```bash +helm install rundeckpro . \ + --set-file kubeconfig=/path/to/kubeconfig +``` + +### 3. Realm Properties File Secret + +The realm.properties file defines local user accounts for file-based authentication: + +```bash +helm install rundeckpro . \ + --set-file realm=/path/to/realm.properties +``` + +**Example realm.properties file**: +```properties +# Format: username:password,user,role1,role2 +admin:admin,user,admin,architect,deploy,build +user:user,user,dev,ops +``` + +### 4. Database Password Secret + +The database password **is sensitive** and should **not** be written to any file or included in `values.yaml`. Create it directly in Kubernetes: + +```bash +kubectl create secret generic database-password \ + --from-literal=password='YOUR_SECURE_PASSWORD' \ + --namespace=rundeck +``` + +**Important:** Make sure the secret name matches what's referenced in the deployment template (`database-password`). + +## Required Values Configuration + +Before deploying, you must customize these values in `values.yaml` or via `--set` flags: + +### Namespace +```yaml +namespace: rundeck # Your Kubernetes namespace +``` + +### Ingress Configuration +```yaml +ingress: + host: rundeck.example.com # Your domain + annotations: + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:region:account:certificate/id + external-dns.alpha.kubernetes.io/hostname: "rundeck.example.com" +``` + +### Rundeck Configuration +```yaml +rundeck: + env: + RUNDECK_GRAILS_URL: "https://rundeck.example.com" + RUNDECK_DATABASE_URL: "jdbc:mysql://your-rds-endpoint.rds.amazonaws.com/rundeck?autoReconnect=true" + RUNDECK_DATABASE_USERNAME: "rundeckuser" + RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_BUCKET: "your-s3-bucket" + RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_REGION: "us-west-2" +``` + +### LDAP/AD Configuration (Optional) + +If using LDAP/AD authentication, configure these values: +```yaml +rundeck: + env: + RUNDECK_JAAS_LDAP_PROVIDERURL: "ldap://your-ldap-server.example.com:389" + RUNDECK_JAAS_LDAP_BINDDN: "CN=rundeck,OU=Users,DC=example,DC=com" + RUNDECK_JAAS_LDAP_BINDPASSWORD: "changeme" + RUNDECK_JAAS_LDAP_USERBASEDN: "OU=Users,DC=example,DC=com" +``` + +**Note:** If not using LDAP, remove these settings from `values.yaml`. + +## Installation + +### 1. Create Namespace + +```bash +kubectl create namespace rundeck +``` + +### 2. Create Database Password Secret + +```bash +kubectl create secret generic database-password \ + --from-literal=password='YOUR_DATABASE_PASSWORD' \ + --namespace=rundeck +``` + +### 3. Prepare Configuration Files + +Create or obtain these files: +- `admin-role.aclpolicy` - Admin ACL permissions +- `realm.properties` - Local user accounts +- `kubeconfig` - (Optional) Kubernetes access + +### 4. Customize values.yaml + +Edit `values.yaml` to set your specific configuration values (see Required Values Configuration above). + +### 5. Install the Chart + +```bash +helm install rundeckpro ./rundeckpro \ + --namespace=rundeck \ + --set-file aclFile=./admin-role.aclpolicy \ + --set-file realm=./realm.properties \ + --set-file kubeconfig=/path/to/kubeconfig \ + --values values.yaml +``` + +### 6. Verify Deployment + +```bash +# Check pods +kubectl get pods -n rundeck + +# Check service +kubectl get svc -n rundeck + +# Check ingress +kubectl get ingress -n rundeck + +# View logs +kubectl logs -n rundeck -l app.kubernetes.io/name=rundeckpro --tail=100 +``` + +## Upgrading + +To upgrade the release with new values or chart changes: + +```bash +helm upgrade rundeckpro ./rundeckpro \ + --namespace=rundeck \ + --set-file aclFile=./admin-role.aclpolicy \ + --set-file realm=./realm.properties \ + --values values.yaml +``` + +## Uninstalling + +To remove all resources created by this chart: + +```bash +helm uninstall rundeckpro --namespace=rundeck +``` + +**Note:** This will delete all Kubernetes resources associated with the release, including deployments, services, ingress, and secrets. It will NOT delete: +- The RDS database +- S3 bucket and logs +- Route53 records (may persist depending on ExternalDNS configuration) + +## Configuration Examples + +### Production Environment + +```yaml +replicaCount: 3 + +resources: + requests: + memory: "4Gi" + cpu: "1000m" + limits: + memory: "6Gi" + cpu: "2000m" + +rundeck: + env: + JAVA_OPTS: "-Xms4g -Xmx5g" +``` + +### Development Environment + +```yaml +replicaCount: 1 + +resources: + requests: + memory: "2Gi" + cpu: "500m" + limits: + memory: "3Gi" + cpu: "1000m" + +rundeck: + env: + JAVA_OPTS: "-Xms2g -Xmx2.5g" +``` + +### Using Custom Values File + +```bash +# Create custom-values.yaml with environment-specific overrides +helm install rundeckpro ./rundeckpro \ + --namespace=rundeck \ + --values values.yaml \ + --values custom-values.yaml \ + --set-file aclFile=./admin-role.aclpolicy +``` + +## Troubleshooting + +### Pods Not Starting + +Check pod status and logs: +```bash +kubectl get pods -n rundeck +kubectl describe pod -n rundeck +kubectl logs -n rundeck +``` + +### Database Connection Issues + +Verify database secret and connectivity: +```bash +kubectl get secret database-password -n rundeck -o yaml +kubectl exec -it -n rundeck -- nc -zv your-rds-endpoint 3306 +``` + +### Ingress/ALB Issues + +Check ingress and ALB controller logs: +```bash +kubectl describe ingress -n rundeck +kubectl logs -n kube-system deployment/aws-load-balancer-controller +``` + +### DNS Not Resolving + +Check ExternalDNS logs: +```bash +kubectl logs -n kube-system deployment/external-dns +``` + +## Advanced Configuration + +### Custom Node Selector + +```yaml +nodeSelector: + workload-type: rundeck + environment: production +``` + +### Pod Anti-Affinity + +```yaml +affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - rundeckpro + topologyKey: kubernetes.io/hostname +``` + +### Resource Quotas + +```yaml +resources: + requests: + memory: "3Gi" + cpu: "800m" + limits: + memory: "3.5Gi" + cpu: "950m" +``` + +## Security Best Practices + +1. **Never commit sensitive values** to version control +2. **Use Kubernetes secrets** for all passwords and tokens +3. **Enable RBAC** on your EKS cluster +4. **Use IAM roles** for AWS service access (IRSA) +5. **Regularly update** Rundeck image versions +6. **Enable audit logging** in Rundeck +7. **Use SSL/TLS** for all connections +8. **Implement network policies** to restrict pod communication + +## Additional Resources + +- [Rundeck Documentation](https://docs.rundeck.com/) +- [Helm Documentation](https://helm.sh/docs/) +- [AWS EKS Best Practices](https://aws.github.io/aws-eks-best-practices/) + +## Support + +For issues and questions: +- [Rundeck Community Forums](https://community.pagerduty.com/) +- [PagerDuty Support](https://support.pagerduty.com/) +- [GitHub Issues](https://github.com/rundeck/docker-zoo/issues) + +## License + +This Helm chart is provided as-is for deploying PagerDuty Runbook Automation. Refer to your Rundeck Enterprise license for application usage terms. diff --git a/kubernetes/helm/rundeckpro/templates/_helpers.tpl b/kubernetes/helm/rundeckpro/templates/_helpers.tpl new file mode 100644 index 0000000..7115da5 --- /dev/null +++ b/kubernetes/helm/rundeckpro/templates/_helpers.tpl @@ -0,0 +1,45 @@ +{{/* +Return the chart name. +*/}} +{{- define "rundeckpro.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Return the fully-qualified name. +*/}} +{{- define "rundeckpro.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "rundeckpro.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "rundeckpro.labels" -}} +helm.sh/chart: {{ include "rundeckpro.chart" . }} +{{ include "rundeckpro.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "rundeckpro.selectorLabels" -}} +app.kubernetes.io/name: {{ include "rundeckpro.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/kubernetes/helm/rundeckpro/templates/configMap.yaml b/kubernetes/helm/rundeckpro/templates/configMap.yaml new file mode 100644 index 0000000..a18ca03 --- /dev/null +++ b/kubernetes/helm/rundeckpro/templates/configMap.yaml @@ -0,0 +1,45 @@ +{{- if .Values.configMap.nodeSources }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.configMap.nodeSources.name }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +data: + resources.yaml: | + # Example node definitions + # Replace with your actual node inventory + example-node-01: + nodename: example-node-01 + hostname: node-01.example.com + osFamily: linux + tags: linux,production + example-node-02: + nodename: example-node-02 + hostname: node-02.example.com + osFamily: linux + tags: linux,staging + example-windows-01: + nodename: example-windows-01 + hostname: win-01.example.com + osFamily: windows + tags: windows,production +{{- end }} +--- +{{- if .Values.configMap.cyberarkCerts }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.configMap.cyberarkCerts.name }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +data: + # Add your certificate data here if using CyberArk integration + # Example: + # ca-cert.pem: | + # -----BEGIN CERTIFICATE----- + # ... + # -----END CERTIFICATE----- +{{- end }} diff --git a/kubernetes/helm/rundeckpro/templates/deployment.yaml b/kubernetes/helm/rundeckpro/templates/deployment.yaml new file mode 100644 index 0000000..bc9ece7 --- /dev/null +++ b/kubernetes/helm/rundeckpro/templates/deployment.yaml @@ -0,0 +1,184 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "rundeckpro.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + strategy: + type: {{ .Values.deployment.strategy.type | default "RollingUpdate" }} + selector: + matchLabels: + {{- include "rundeckpro.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "rundeckpro.selectorLabels" . | nindent 8 }} + spec: + securityContext: + runAsUser: 1000 + fsGroup: 0 + containers: + - name: rundeck + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: {{ .Values.service.targetPort }} + name: http + protocol: TCP + env: + - name: JAVA_OPTS + value: {{ .Values.rundeck.env.JAVA_OPTS | quote }} + - name: RUNDECK_GRAILS_URL + value: {{ .Values.rundeck.env.RUNDECK_GRAILS_URL | quote }} + + # Cluster configuration + - name: RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_INTERVAL + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_INTERVAL | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_HEARBEAT_DELAY + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_HEARBEAT_DELAY | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_CONSIDERINACTIVE + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_CONSIDERINACTIVE | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_CONSIDERDEAD + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_CONSIDERDEAD | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_ENABLED + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_ENABLED | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_POLICY + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_POLICY | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_DELAY + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_DELAY | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_SLEEP + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_SLEEP | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_ENABLED + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_ENABLED | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_POLICY + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_POLICY | quote }} + - name: RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_ALLOWEDTAGS + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_ALLOWEDTAGS | quote }} + + # Database configuration + - name: RUNDECK_DATABASE_DRIVER + value: {{ .Values.rundeck.env.RUNDECK_DATABASE_DRIVER | quote }} + - name: RUNDECK_DATABASE_URL + value: {{ .Values.rundeck.env.RUNDECK_DATABASE_URL | quote }} + - name: RUNDECK_DATABASE_USERNAME + value: {{ .Values.rundeck.env.RUNDECK_DATABASE_USERNAME | quote }} + - name: RUNDECK_DATABASE_PASSWORD + valueFrom: + secretKeyRef: + name: database-password + key: password + + # S3 Log Storage + - name: RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_NAME + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_NAME | quote }} + - name: RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_BUCKET + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_BUCKET | quote }} + - name: RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_REGION + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_REGION | quote }} + - name: RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_PATH + value: {{ .Values.rundeck.env.RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_PATH | quote }} + + # Server configuration + - name: RUNDECK_SERVER_FORWARDED + value: {{ .Values.rundeck.env.RUNDECK_SERVER_FORWARDED | quote }} + - name: RUNDECK_SERVER_SESSION_TIMEOUT + value: {{ .Values.rundeck.env.RUNDECK_SERVER_SESSION_TIMEOUT | quote }} + + # UI configuration + - name: RUNDECK_GUI_INSTANCENAME + value: {{ .Values.rundeck.env.RUNDECK_GUI_INSTANCENAME | quote }} + + # Runner feature + - name: RUNDECK_RUNNER_FEATURE_ENABLED + value: {{ .Values.rundeck.env.RUNDECK_RUNNER_FEATURE_ENABLED | quote }} + + # LDAP/AD authentication (if configured) + {{- if .Values.rundeck.env.RUNDECK_JAAS_MODULES_0 }} + - name: RUNDECK_JAAS_MODULES_0 + value: {{ .Values.rundeck.env.RUNDECK_JAAS_MODULES_0 | quote }} + - name: RUNDECK_JAAS_LDAP_FLAG + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_FLAG | quote }} + - name: RUNDECK_JAAS_LDAP_PROVIDERURL + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_PROVIDERURL | quote }} + - name: RUNDECK_JAAS_LDAP_BINDDN + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_BINDDN | quote }} + - name: RUNDECK_JAAS_LDAP_BINDPASSWORD + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_BINDPASSWORD | quote }} + - name: RUNDECK_JAAS_LDAP_USERBASEDN + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_USERBASEDN | quote }} + - name: RUNDECK_JAAS_LDAP_ROLEBASEDN + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_ROLEBASEDN | quote }} + - name: RUNDECK_JAAS_LDAP_ROLEOBJECTCLASS + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_ROLEOBJECTCLASS | quote }} + - name: RUNDECK_JAAS_LDAP_ROLENAMEATTRIBUTE + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_ROLENAMEATTRIBUTE | quote }} + - name: RUNDECK_JAAS_LDAP_ROLEMEMBERATTRIBUTE + value: {{ .Values.rundeck.env.RUNDECK_JAAS_LDAP_ROLEMEMBERATTRIBUTE | quote }} + {{- end }} + + # File-based authentication + - name: RUNDECK_JAAS_MODULES_1 + value: {{ .Values.rundeck.env.RUNDECK_JAAS_MODULES_1 | quote }} + - name: RUNDECK_JAAS_FILE_FLAG + value: {{ .Values.rundeck.env.RUNDECK_JAAS_FILE_FLAG | quote }} + + volumeMounts: + - name: acl + mountPath: /home/rundeck/etc/admin-role.aclpolicy + subPath: admin-role.aclpolicy + - name: kubeconfig + mountPath: /home/rundeck/.kube/config + subPath: config + - name: realm + mountPath: /home/rundeck/server/config/realm.properties + subPath: realm.properties + {{- if .Values.configMap.nodeSources }} + - name: node-sources + mountPath: {{ .Values.configMap.nodeSources.mountPath }} + {{- end }} + {{- if .Values.configMap.cyberarkCerts }} + - name: cyberark-certs + mountPath: {{ .Values.configMap.cyberarkCerts.mountPath }} + {{- end }} + + volumes: + - name: acl + secret: + secretName: {{ .Values.secrets.acl.name }} + - name: kubeconfig + secret: + secretName: {{ .Values.secrets.kubeconfig.name }} + - name: realm + secret: + secretName: {{ .Values.secrets.realm.name }} + {{- if .Values.configMap.nodeSources }} + - name: node-sources + configMap: + name: {{ .Values.configMap.nodeSources.name }} + items: + - key: resources.yaml + path: resources.yaml + {{- end }} + {{- if .Values.configMap.cyberarkCerts }} + - name: cyberark-certs + configMap: + name: {{ .Values.configMap.cyberarkCerts.name }} + {{- end }} + + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/kubernetes/helm/rundeckpro/templates/ingress.yaml b/kubernetes/helm/rundeckpro/templates/ingress.yaml new file mode 100644 index 0000000..25964eb --- /dev/null +++ b/kubernetes/helm/rundeckpro/templates/ingress.yaml @@ -0,0 +1,24 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "rundeckpro.fullname" . }}-ingress + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.ingress.annotations | nindent 4 }} +spec: + ingressClassName: {{ .Values.ingress.ingressClassName }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "rundeckpro.fullname" . }} + port: + number: {{ .Values.service.port }} +{{- end }} diff --git a/kubernetes/helm/rundeckpro/templates/secrets.yaml b/kubernetes/helm/rundeckpro/templates/secrets.yaml new file mode 100644 index 0000000..4d52270 --- /dev/null +++ b/kubernetes/helm/rundeckpro/templates/secrets.yaml @@ -0,0 +1,35 @@ +# ACL Secret +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.secrets.acl.name }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +type: Opaque +data: + admin-role.aclpolicy: {{ .Values.aclFile | b64enc }} +--- +# Kubeconfig Secret +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.secrets.kubeconfig.name }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +type: Opaque +data: + config: {{ .Values.kubeconfig | b64enc }} +--- +# realm.properties Secret +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.secrets.realm.name }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +type: Opaque +data: + realm.properties: {{ .Values.realm | b64enc }} diff --git a/kubernetes/helm/rundeckpro/templates/service.yaml b/kubernetes/helm/rundeckpro/templates/service.yaml new file mode 100644 index 0000000..6b91c7a --- /dev/null +++ b/kubernetes/helm/rundeckpro/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "rundeckpro.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + {{- include "rundeckpro.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - protocol: TCP + port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} + name: http + selector: + {{- include "rundeckpro.selectorLabels" . | nindent 4 }} + sessionAffinity: ClientIP + sessionAffinityConfig: + clientIP: + timeoutSeconds: 86400 diff --git a/kubernetes/helm/rundeckpro/values.yaml b/kubernetes/helm/rundeckpro/values.yaml new file mode 100644 index 0000000..8afc1cb --- /dev/null +++ b/kubernetes/helm/rundeckpro/values.yaml @@ -0,0 +1,147 @@ +# Default values for rundeckpro Helm chart +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Number of Rundeck replicas to deploy +replicaCount: 2 + +# Kubernetes namespace for Rundeck resources +namespace: rundeck + +# Docker image configuration +image: + repository: rundeckpro/enterprise + tag: 5.17.0-20251103 + pullPolicy: Always + +# Kubernetes Service configuration +service: + type: ClusterIP + port: 443 + targetPort: 4440 + +# Ingress configuration for external access +ingress: + enabled: true + ingressClassName: alb + # Replace with your own domain + host: rundeck.example.com + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]' + # Replace with your ACM certificate ARN + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:123456789012:certificate/your-certificate-id + alb.ingress.kubernetes.io/ssl-redirect: '443' + alb.ingress.kubernetes.io/healthcheck-path: /health + alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.type=app_cookie,stickiness.app_cookie.cookie_name=JSESSIONID,stickiness.app_cookie.duration_seconds=86400 + # Replace with your domain for ExternalDNS + external-dns.alpha.kubernetes.io/hostname: "rundeck.example.com" + +# Rundeck application configuration +rundeck: + env: + # JVM memory settings + JAVA_OPTS: "-Xms2g -Xmx2.5g" + + # Rundeck URL - replace with your domain + RUNDECK_GRAILS_URL: "https://rundeck.example.com" + + # Database configuration - replace with your RDS endpoint + RUNDECK_DATABASE_DRIVER: "org.mariadb.jdbc.Driver" + RUNDECK_DATABASE_URL: "jdbc:mysql://your-rds-endpoint.rds.amazonaws.com/rundeck?autoReconnect=true&allowPublicKeyRetrieval=true&useSSL=false" + RUNDECK_DATABASE_USERNAME: "rundeckuser" + # Database password is injected via Kubernetes secret (see README) + + # Cluster mode configuration + RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_INTERVAL: "30" + RUNDECK_PLUGIN_CLUSTER_HEARBEAT_DELAY: "10" + RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_CONSIDERINACTIVE: "150" + RUNDECK_PLUGIN_CLUSTER_HEARTBEAT_CONSIDERDEAD: "300" + RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_ENABLED: "true" + RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_POLICY: "any" + RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_DELAY: "60" + RUNDECK_PLUGIN_CLUSTER_AUTOTAKEOVER_SLEEP: "300" + RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_ENABLED: "true" + RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_POLICY: "Load" + RUNDECK_PLUGIN_CLUSTER_REMOTEEXECUTION_ALLOWEDTAGS: "*" + + # Server configuration + RUNDECK_SERVER_FORWARDED: "true" + RUNDECK_SERVER_SESSION_TIMEOUT: "1800" + + # S3 Log Storage configuration - replace with your S3 bucket + RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_NAME: "com.rundeck.rundeckpro.amazon-s3" + RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_BUCKET: "your-s3-bucket-name" + RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_REGION: "us-west-2" + RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_PATH: "rundeck-logs/${job.project}/${job.execid}.log" + + # UI configuration + RUNDECK_GUI_INSTANCENAME: "true" + + # Runner feature + RUNDECK_RUNNER_FEATURE_ENABLED: "true" + + # LDAP/AD authentication (optional - remove if not using) + RUNDECK_JAAS_MODULES_0: "JettyCombinedLdapLoginModule" + RUNDECK_JAAS_LDAP_FLAG: sufficient + RUNDECK_JAAS_LDAP_PROVIDERURL: "ldap://your-ldap-server.example.com:389" + RUNDECK_JAAS_LDAP_BINDDN: "CN=rundeck,OU=Users,DC=example,DC=com" + RUNDECK_JAAS_LDAP_BINDPASSWORD: "changeme" + RUNDECK_JAAS_LDAP_USERBASEDN: "OU=Users,DC=example,DC=com" + RUNDECK_JAAS_LDAP_ROLEBASEDN: "DC=example,DC=com" + RUNDECK_JAAS_LDAP_ROLEOBJECTCLASS: "group" + RUNDECK_JAAS_LDAP_ROLENAMEATTRIBUTE: "cn" + RUNDECK_JAAS_LDAP_ROLEMEMBERATTRIBUTE: "member" + + # File-based authentication + RUNDECK_JAAS_MODULES_1: PropertyFileLoginModule + RUNDECK_JAAS_FILE_FLAG: sufficient + +# Deployment strategy +deployment: + strategy: + type: Recreate # or "RollingUpdate" + +# Kubernetes secrets references +secrets: + acl: + name: rundeckpro-admin-acl + kubeconfig: + name: kubeconfig + realm: + name: realm-properties + +# ConfigMap references +configMap: + nodeSources: + name: node-sources + mountPath: /home/rundeck/resources.yaml + cyberarkCerts: + name: cyberark-certs + mountPath: /home/rundeck/certs + +# Resource requests and limits +resources: + requests: + memory: "3Gi" + cpu: "800m" + limits: + memory: "3.5Gi" + cpu: "950m" + +# Node selection, tolerations, and affinity (optional) +nodeSelector: {} +tolerations: [] +affinity: {} + +# Values for --set-file parameters (see README for usage) +aclFile: "" +kubeconfig: "" +realm: "" + +# CyberArk certificate configuration (optional) +cyberarkCerts: + keystorePassword: changeit + clientkeystore: clientkeystore