Kubernetes with Ansible

From Knowledge Center
Jump to: navigation, search

Install the required kubernetes plugin:

$ ansible-galaxy collection install community.kubernetes

The kubernetes playbook:

$ cat playbook.yml
---
- name: Apply kubernetes namespace
  hosts: tooling
  gather_facts: yes
  roles:
    - { role: ./roles/kubernetes/test }
    - { role: ./roles/kubernetes/mysql }

The test task:

$ cat roles/kubernetes/test/tasks/main.yml
---
# https://docs.ansible.com/ansible/latest/collections/community/kubernetes/k8s_module.html
- name: Include role variables
  include_vars:
    file: vars/all.yml
    
- name: Ensure kubernetes namespace is present
  community.kubernetes.k8s:
    name: testing
    api_version: v1
    kind: Namespace
    state: present

The test task variables:

$ cat roles/kubernetes/test/vars/all.yml
ansible_python_interpreter: /usr/bin/python3

The main kubernetes task:

$ cat roles/kubernetes/mysql/tasks/main.yml
---
# https://docs.ansible.com/ansible/latest/collections/community/kubernetes/k8s_module.html
- name: Ensure kubernetes namespace is present
  community.kubernetes.k8s:
    name: databases
    api_version: v1
    kind: Namespace
    state: present
    
# https://kubernetes.io/docs/tasks/run-application/run-single-instance-stateful-application/

- name: persistent volume
  community.kubernetes.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: mysql-pv-volume
        namespace: databases
        labels:
          type: local
      spec:
        storageClassName: local-path
        capacity:
          storage: 5Gi
        accessModes:
          - ReadWriteOnce
        hostPath:
          path: "/volumes/mysql"

- name: persistent volume claim
  community.kubernetes.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: mysql-pv-claim
        namespace: databases
      spec:
        storageClassName: local-path
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
            
- name: Create a Service object from an inline definition
  community.kubernetes.k8s:
    state: present
    definition:
      apiVersion: v1
      kind: Service
      metadata:
        name: mysql
        namespace: databases
        labels:
          app: mysql
      spec:
        selector:
          app: mysql
        ports:
        - protocol: TCP
          targetPort: 3306
          name: port-3306-tcp
          port: 3306
    
- name: deployment
  community.kubernetes.k8s:
    state: present
    definition:
      apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
      kind: Deployment
      metadata:
        name: mysql
        namespace: databases
      spec:
        selector:
          matchLabels:
            app: mysql
        strategy:
          type: Recreate
        template:
          metadata:
            labels:
              app: mysql
          spec:
            containers:
            - image: mysql:5.7
              name: mysql
              env:
                # Use secret in real usage
              - name: MYSQL_ROOT_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: mysql-root-password
                    key: env.MYSQL_ROOT_PASSWORD
              ports:
              - containerPort: 3306
                name: mysql
              volumeMounts:
              - name: mysql-persistent-storage
                mountPath: /var/lib/mysql
            volumes:
            - name: mysql-persistent-storage
              persistentVolumeClaim:
                claimName: mysql-pv-claim

Inventory:

$ cat inventory.ini
[tooling]
tooling-host ansible_host=${{secrets.TOOLING_SERVER_IP}} ansible_user=${{secrets.ANSIBLE_USER}}
[tooling:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'

Run:

$ ansible-playbook -i inventory.ini playbook.yml
[tooling]
tooling-host ansible_host=${{secrets.TOOLING_SERVER_IP}} ansible_user=${{secrets.ANSIBLE_USER}}
[tooling:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'

Verify:

$ kubectl get deployments -n databases -o wide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES      SELECTOR
mysql   1/1     1            1           107s   mysql        mysql:5.7   app=mysql

Run a pod and logon to mysql:

$ kubectl run -it --rm --image=mysql:5.7 --restart=Never mysql-client -- mysql -h mysql.databases.svc.cluster.local -p$pass

mysql> create database test;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql>

Resources: