--- # Set kubeconfig path if not already set - name: Set kubeconfig path ansible.builtin.set_fact: KUBECONFIG: "{{ playbook_dir }}/kubeconfig/config" when: KUBECONFIG is not defined tags: [karpenter] # Configure image pull secret for IKS - name: Configure ICR pull secret for IKS block: - name: Get default ICR pull secret kubernetes.core.k8s_info: api_version: v1 kind: Secret name: all-icr-io namespace: default register: icr_secret environment: KUBECONFIG: "{{ KUBECONFIG }}" ignore_errors: yes - name: Copy ICR pull secret to kube-system namespace kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Secret metadata: name: all-icr-io namespace: kube-system type: "{{ icr_secret.resources[0].type }}" data: "{{ icr_secret.resources[0].data }}" environment: KUBECONFIG: "{{ KUBECONFIG }}" when: - icr_secret is succeeded - icr_secret.resources | length > 0 tags: [karpenter] # Configure IBM Cloud credentials for storage - name: Configure IBM Cloud credentials for storage kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Secret metadata: name: ibm-cloud-credentials namespace: default type: Opaque stringData: "ibm-credentials.env": | IBMCLOUD_APIKEY={{ IBM_CLOUD_TOKEN }} environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] - name: Add Karpenter chart repo for IKS kubernetes.core.helm_repository: name: pfeifferj repo_url: "https://pfeifferj.github.io/karpenter-provider-ibm-cloud" environment: KUBECONFIG: "{{ KUBECONFIG }}" ignore_errors: yes tags: [karpenter] - name: Update Helm repositories ansible.builtin.command: helm repo update environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] - name: Deploy Karpenter Autoscaler for IKS kubernetes.core.helm: name: karpenter chart_ref: pfeifferj/karpenter-ibm chart_version: "0.35.0" release_namespace: karpenter create_namespace: true values: credentials: ibm_api_key: "{{ IBM_CLOUD_TOKEN }}" vpc_api_key: "{{ IBM_VPC_API_KEY | default(IBM_CLOUD_TOKEN) }}" region: "us-south" image: repository: us.icr.io/pfeifferj/karpenter-controller tag: v0.2.24 pullPolicy: Always digest: "" imagePullSecrets: - name: icr-secret logLevel: "debug" verboseLogLevel: "5" debug: "true" controllerVerbosity: "4" controllerLogLevel: "debug" # IKS Integration Configuration - using correct Helm chart structure iksClusterID: "d1jnl8od0fjpn1553n3g" clusterName: "minimal-karpenter-test" bootstrapMode: "iks-api" environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] # Create ICR image pull secret for karpenter namespace (after namespace is created) - name: Create ICR image pull secret kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Secret metadata: name: icr-secret namespace: karpenter type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: "{{ ('{\"auths\":{\"us.icr.io\":{\"username\":\"iamapikey\",\"password\":\"' + IBM_CLOUD_TOKEN + '\"}}}') | b64encode }}" environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] # Patch service account to use the image pull secret - name: Patch karpenter service account with image pull secret kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: ServiceAccount metadata: name: karpenter namespace: karpenter imagePullSecrets: - name: icr-secret merge_type: merge environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] - name: Create IBMNodeClass kubernetes.core.k8s: state: present definition: apiVersion: karpenter.ibm.sh/v1alpha1 kind: IBMNodeClass metadata: name: auto-placement spec: region: us-south vpc: "{{ VPC_ID }}" zone: us-south-1 subnet: "{{ SUBNET_ID.US_SOUTH_1 }}" # Use ONLY instanceProfile, not instanceRequirements # IMPORTANT: Use dashes in instance profile names (bx2-2x8) not dots (bx2.2x8) instanceProfile: bx2-2x8 placementStrategy: zoneBalance: Balanced subnetSelection: minimumAvailableIPs: 10 # Use the full IBM Cloud image name image: ibm-ubuntu-24-04-2-minimal-amd64-4 # IKS-specific configuration bootstrapMode: iks-api iksClusterID: "d1jnl8od0fjpn1553n3g" environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] - name: Create NodePool kubernetes.core.k8s: state: present definition: apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: default spec: template: metadata: labels: provisioner: karpenter-ibm spec: requirements: - key: kubernetes.io/arch operator: In values: ["amd64"] - key: kubernetes.io/os operator: In values: ["linux"] # Removed restricted label requirement nodeClassRef: group: karpenter.ibm.sh kind: IBMNodeClass name: auto-placement taints: - key: karpenter.ibm.sh/provisioned value: "true" effect: NoSchedule expireAfter: 720h disruption: consolidateAfter: 30s consolidationPolicy: WhenEmpty budgets: - nodes: "10%" limits: cpu: 1000 memory: 1000Gi environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] - name: Verify Karpenter resources kubernetes.core.k8s_info: api_version: "{{ item.api }}" kind: "{{ item.kind }}" namespace: "{{ item.namespace | default(omit) }}" register: karpenter_resources loop: - { api: "karpenter.ibm.sh/v1alpha1", kind: "IBMNodeClass" } - { api: "karpenter.sh/v1", kind: "NodePool" } - { api: "apps/v1", kind: "Deployment", namespace: "karpenter" } environment: KUBECONFIG: "{{ KUBECONFIG }}" tags: [karpenter] - name: Display Karpenter status ansible.builtin.debug: msg: "Karpenter installed successfully. Found {{ item.resources | length }} {{ item.item.kind }}(s)" loop: "{{ karpenter_resources.results }}" tags: [karpenter]